Updated on 2026-08-14
This commit is contained in:
commit
f517f859db
23 changed files with 316 additions and 254 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.domain.userWalletList.implementation
|
|||
import com.tangem.common.*
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListError
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey
|
||||
|
|
@ -56,8 +57,8 @@ internal class BiometricUserWalletsListManager(
|
|||
override val walletsCount: Int
|
||||
get() = state.value.userWallets.size
|
||||
|
||||
override suspend fun unlock(throwIfNotAllWalletsUnlocked: Boolean): CompletionResult<UserWallet> {
|
||||
return unlockWithBiometryInternal()
|
||||
override suspend fun unlock(type: UnlockType): CompletionResult<UserWallet> {
|
||||
return unlockAndSetSelectedUserWallet(type)
|
||||
.mapFailure { error ->
|
||||
Timber.e(error, "Unable to unlock user wallets")
|
||||
if (error is UserWalletsListError) {
|
||||
|
|
@ -66,16 +67,8 @@ internal class BiometricUserWalletsListManager(
|
|||
UserWalletsListError.UnableToUnlockUserWallets(error)
|
||||
}
|
||||
}
|
||||
.map {
|
||||
val userWallets = state.value.userWallets
|
||||
|
||||
if (throwIfNotAllWalletsUnlocked && userWallets.any(UserWallet::isLocked)) {
|
||||
Timber.e("Some user wallets remain locked")
|
||||
throw UserWalletsListError.NotAllUserWalletsUnlocked
|
||||
}
|
||||
|
||||
val selectedUserWallet = selectedUserWalletSync
|
||||
if (selectedUserWallet == null) {
|
||||
.map { selectedUserWallet ->
|
||||
if (selectedUserWallet == null || selectedUserWallet.isLocked) {
|
||||
Timber.e("Unable to find selected user wallet")
|
||||
throw UserWalletsListError.NoUserWalletSelected
|
||||
} else {
|
||||
|
|
@ -186,99 +179,116 @@ internal class BiometricUserWalletsListManager(
|
|||
changeSelectedUserWallet: Boolean,
|
||||
canOverridePublicInfo: Boolean,
|
||||
): CompletionResult<Unit> {
|
||||
return saveEncryptionKeyIfNotNull(userWallet)
|
||||
.flatMap { sensitiveInformationRepository.save(userWallet, encryptionKey = it) }
|
||||
.flatMap { publicInformationRepository.save(userWallet, canOverridePublicInfo) }
|
||||
.map {
|
||||
if (changeSelectedUserWallet) {
|
||||
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 },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun unlockWithBiometryInternal(): CompletionResult<Unit> {
|
||||
return keysRepository.getAll()
|
||||
.map { keys ->
|
||||
state.update { prevState ->
|
||||
prevState.copy(
|
||||
encryptionKeys = (keys + prevState.encryptionKeys).distinctBy { it.walletId },
|
||||
)
|
||||
}
|
||||
}
|
||||
.flatMap { loadModels() }
|
||||
.map {
|
||||
state.update { prevState ->
|
||||
val hasLockedUserWallets = prevState.userWallets.any { it.isLocked }
|
||||
prevState.copy(isLocked = hasLockedUserWallets)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveEncryptionKeyIfNotNull(userWallet: UserWallet): CompletionResult<ByteArray?> {
|
||||
val encryptionKey = userWallet.scanResponse.card.encryptionKey
|
||||
?.let { UserWalletEncryptionKey(userWallet.walletId, it) }
|
||||
?: return CompletionResult.Success(Unit) // No encryption key, no need to save
|
||||
|
||||
return if (encryptionKey != null) {
|
||||
keysRepository.save(encryptionKey)
|
||||
.doOnSuccess {
|
||||
state.update { prevState ->
|
||||
prevState.copy(
|
||||
encryptionKeys = prevState.encryptionKeys
|
||||
.plus(encryptionKey)
|
||||
.distinctBy { it.walletId },
|
||||
)
|
||||
}
|
||||
return keysRepository.save(encryptionKey)
|
||||
.flatMap { sensitiveInformationRepository.save(userWallet, encryptionKey = encryptionKey.encryptionKey) }
|
||||
.flatMap { publicInformationRepository.save(userWallet, canOverridePublicInfo) }
|
||||
.flatMap {
|
||||
loadUserWallets(
|
||||
encryptionKeys = state.value.encryptionKeys
|
||||
.plus(encryptionKey)
|
||||
.distinctBy(UserWalletEncryptionKey::walletId),
|
||||
)
|
||||
}
|
||||
.doOnSuccess { loadedState ->
|
||||
if (changeSelectedUserWallet) {
|
||||
selectedUserWalletRepository.set(userWallet.walletId)
|
||||
|
||||
state.value = loadedState.copy(
|
||||
selectedUserWalletId = userWallet.walletId,
|
||||
)
|
||||
} else {
|
||||
state.value = loadedState
|
||||
}
|
||||
.map { encryptionKey.encryptionKey }
|
||||
} else {
|
||||
CompletionResult.Success(data = null)
|
||||
}
|
||||
}
|
||||
.map { /* Type erasing */ }
|
||||
}
|
||||
|
||||
private suspend fun loadModels(): CompletionResult<Unit> {
|
||||
return getSavedUserWallets()
|
||||
.map { userWallets ->
|
||||
if (userWallets.isNotEmpty()) {
|
||||
state.update { prevState ->
|
||||
val wallets = (userWallets + prevState.userWallets).distinctBy { it.walletId }
|
||||
private suspend fun unlockAndSetSelectedUserWallet(type: UnlockType): CompletionResult<UserWallet?> {
|
||||
return keysRepository.getAll()
|
||||
.flatMap { encryptionKeys ->
|
||||
loadUserWallets(
|
||||
encryptionKeys = state.value.encryptionKeys
|
||||
.plus(encryptionKeys)
|
||||
.distinctBy(UserWalletEncryptionKey::walletId),
|
||||
)
|
||||
}
|
||||
.map { loadedState ->
|
||||
when (type) {
|
||||
UnlockType.ALL -> {
|
||||
if (loadedState.isLocked) {
|
||||
Timber.e("Some user wallets remain locked")
|
||||
|
||||
prevState.copy(
|
||||
userWallets = wallets,
|
||||
selectedUserWalletId = findOrSetSelectedWalletId(prevState.selectedUserWalletId, wallets),
|
||||
state.value = loadedState
|
||||
|
||||
throw UserWalletsListError.NotAllUserWalletsUnlocked
|
||||
} else {
|
||||
val selectedWallet = findOrSetSelectedWallet(
|
||||
state.value.selectedUserWalletId,
|
||||
loadedState.userWallets,
|
||||
)
|
||||
|
||||
state.value = loadedState.copy(
|
||||
selectedUserWalletId = selectedWallet?.walletId,
|
||||
)
|
||||
|
||||
selectedWallet
|
||||
}
|
||||
}
|
||||
UnlockType.ANY -> {
|
||||
val selectedWallet = findOrSetSelectedWallet(
|
||||
state.value.selectedUserWalletId,
|
||||
loadedState.userWallets,
|
||||
)
|
||||
|
||||
state.value = loadedState.copy(
|
||||
selectedUserWalletId = selectedWallet?.walletId,
|
||||
)
|
||||
|
||||
selectedWallet
|
||||
}
|
||||
UnlockType.ALL_WITHOUT_SELECT -> {
|
||||
state.value = loadedState
|
||||
|
||||
findSelectedUserWallet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSavedUserWallets(): CompletionResult<List<UserWallet>> {
|
||||
private suspend fun loadUserWallets(encryptionKeys: List<UserWalletEncryptionKey>): CompletionResult<State> {
|
||||
return publicInformationRepository.getAll()
|
||||
.map { it.toUserWallets() }
|
||||
.flatMap { userWallets ->
|
||||
sensitiveInformationRepository.getAll(state.value.encryptionKeys)
|
||||
sensitiveInformationRepository.getAll(encryptionKeys)
|
||||
.map { walletIdToSensitiveInformation ->
|
||||
userWallets.updateWith(walletIdToSensitiveInformation)
|
||||
}
|
||||
}
|
||||
.map { userWallets ->
|
||||
val prevState = state.value
|
||||
|
||||
if (userWallets.isNotEmpty()) {
|
||||
val newUserWallets = (userWallets + prevState.userWallets)
|
||||
.distinctBy(UserWallet::walletId)
|
||||
|
||||
prevState.copy(
|
||||
userWallets = newUserWallets,
|
||||
isLocked = newUserWallets.any(UserWallet::isLocked),
|
||||
)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findOrSetSelectedWalletId(
|
||||
private fun findOrSetSelectedWallet(
|
||||
prevSelectedWalletId: UserWalletId?,
|
||||
userWallets: List<UserWallet>,
|
||||
): UserWalletId? {
|
||||
): UserWallet? {
|
||||
val selectedWalletId = prevSelectedWalletId ?: selectedUserWalletRepository.get()
|
||||
var possibleSelectedUserWallet = findSelectedUserWallet(userWallets, selectedWalletId)
|
||||
|
||||
|
|
@ -290,7 +300,7 @@ internal class BiometricUserWalletsListManager(
|
|||
}
|
||||
}
|
||||
|
||||
return possibleSelectedUserWallet?.walletId
|
||||
return possibleSelectedUserWallet
|
||||
}
|
||||
|
||||
private fun changeSelectedUserWalletIdIfNeeded(walletsIdsToRemove: List<UserWalletId>) {
|
||||
|
|
|
|||
|
|
@ -100,10 +100,10 @@ internal class GeneralUserWalletsListManager(
|
|||
return implementation.value.get(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun unlock(throwIfNotAllWalletsUnlocked: Boolean): CompletionResult<UserWallet> {
|
||||
override suspend fun unlock(type: UserWalletsListManager.Lockable.UnlockType): CompletionResult<UserWallet> {
|
||||
val implementation = implementation.value
|
||||
return if (implementation is UserWalletsListManager.Lockable) {
|
||||
implementation.unlock()
|
||||
implementation.unlock(type)
|
||||
} else {
|
||||
error("RuntimeUserWalletsListManager is not lockable")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ internal class DelegatedKeystoreManager(
|
|||
|
||||
override suspend fun get(
|
||||
masterKeyConfig: KeystoreManager.MasterKeyConfig,
|
||||
keyAliases: Collection<String>,
|
||||
keyAliases: Set<String>,
|
||||
): Map<String, SecretKey> {
|
||||
return keystoreManagerProvider().get(masterKeyConfig, keyAliases)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ internal class BiometricUserWalletsKeysRepository(
|
|||
.doOnFailure { error ->
|
||||
when (error) {
|
||||
is TangemSdkError.KeystoreInvalidated -> {
|
||||
// If the biometric cryptography key was invalidated, then delete all encryption keys
|
||||
getUserWalletsIds().forEach { userWalletId ->
|
||||
deleteEncryptionKey(userWalletId)
|
||||
}
|
||||
|
|
@ -120,7 +119,7 @@ internal class BiometricUserWalletsKeysRepository(
|
|||
}
|
||||
|
||||
private fun deleteEncryptionKey(userWalletId: UserWalletId) {
|
||||
return authenticatedStorage.delete(StorageKey.UserWalletEncryptionKey(userWalletId).name)
|
||||
authenticatedStorage.delete(StorageKey.UserWalletEncryptionKey(userWalletId).name)
|
||||
}
|
||||
|
||||
private suspend fun getUserWalletsIds(): List<UserWalletId> {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.core.navigation.NavigationAction
|
|||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.legacy.unlockIfLockable
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
|
|
@ -86,7 +87,7 @@ internal class WelcomeMiddleware {
|
|||
""".trimIndent(),
|
||||
)
|
||||
|
||||
userWalletsListManager.unlockIfLockable()
|
||||
userWalletsListManager.unlockIfLockable(type = UnlockType.ANY)
|
||||
.doOnFailure { error ->
|
||||
Timber.e(error, "Unable to unlock user wallets with biometrics")
|
||||
store.dispatchWithMain(WelcomeAction.ProceedWithBiometrics.Error(error))
|
||||
|
|
|
|||
|
|
@ -105,16 +105,42 @@ interface UserWalletsListManager {
|
|||
/**
|
||||
* Receive saved [UserWallet]s, populate [userWallets] flow with it and set [isLocked] as false.
|
||||
*
|
||||
* @param throwIfNotAllWalletsUnlocked Indicates that the function must throw
|
||||
* [UserWalletsListError.NotAllUserWalletsUnlocked] if not all user wallets are unlocked.
|
||||
* @param type Defines the behavior of the operation.
|
||||
*
|
||||
* @return [CompletionResult] of operation, with selected [UserWallet]
|
||||
* or null if there is no selected [UserWallet]
|
||||
*/
|
||||
suspend fun unlock(throwIfNotAllWalletsUnlocked: Boolean = false): CompletionResult<UserWallet>
|
||||
suspend fun unlock(type: UnlockType): CompletionResult<UserWallet>
|
||||
|
||||
/** Remove [UserWallet]s from [userWallets] and set [isLocked] as true */
|
||||
fun lock()
|
||||
|
||||
/**
|
||||
* Defines the behavior of the [unlock] operation.
|
||||
* */
|
||||
enum class UnlockType {
|
||||
/**
|
||||
* Ensures that all stored [UserWallet]s are unlocked,
|
||||
* or throws [UserWalletsListError.NotAllUserWalletsUnlocked].
|
||||
*
|
||||
* In this type [selectedUserWallet] is either a previously selected [UserWallet] or the first stored
|
||||
* [UserWallet].
|
||||
* */
|
||||
ALL,
|
||||
|
||||
/**
|
||||
* Ensures that at least one stored [UserWallet] is unlocked,
|
||||
* or throws [UserWalletsListError.NoUserWalletSelected].
|
||||
*
|
||||
* In this type [selectedUserWallet] is the first stored and unlocked [UserWallet].
|
||||
* */
|
||||
ANY,
|
||||
|
||||
/**
|
||||
* Same as [ALL] type, but this type can not change [selectedUserWallet] while unlocking.
|
||||
* */
|
||||
ALL_WITHOUT_SELECT,
|
||||
}
|
||||
}
|
||||
|
||||
// For provider
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.wallets.legacy
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
|
@ -43,8 +44,8 @@ val UserWalletsListManager.isLockedSync: Boolean
|
|||
*
|
||||
* @see UserWalletsListManager.Lockable.unlock
|
||||
* */
|
||||
suspend fun UserWalletsListManager.unlockIfLockable(): CompletionResult<UserWallet> {
|
||||
return asLockable()?.unlock() ?: CompletionResult.Failure(UserWalletsListError.UnableToUnlockUserWallets())
|
||||
suspend fun UserWalletsListManager.unlockIfLockable(type: UnlockType = UnlockType.ANY): CompletionResult<UserWallet> {
|
||||
return asLockable()?.unlock(type) ?: CompletionResult.Failure(UserWalletsListError.UnableToUnlockUserWallets())
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.firstOrNull
|
|||
|
||||
class GetUserWalletUseCase(private val walletsStateHolder: WalletsStateHolder) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<Any, UserWallet> = either {
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<GetUserWalletError, UserWallet> = either {
|
||||
val userWalletsListManager = ensureUserWalletListManagerNotNull(
|
||||
walletsStateHolder = walletsStateHolder,
|
||||
raise = GetUserWalletError::DataError,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import arrow.core.raise.either
|
|||
import arrow.core.raise.ensureNotNull
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListError
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.domain.wallets.legacy.asLockable
|
||||
import com.tangem.domain.wallets.models.UnlockWalletsError
|
||||
|
|
@ -18,27 +19,26 @@ import com.tangem.domain.wallets.models.UnlockWalletsError
|
|||
*/
|
||||
class UnlockWalletsUseCase(private val walletsStateHolder: WalletsStateHolder) {
|
||||
|
||||
suspend operator fun invoke(throwIfNotAllWalletsUnlocked: Boolean = false): Either<UnlockWalletsError, Unit> =
|
||||
either {
|
||||
val userWalletsListManager = ensureNotNull(
|
||||
value = walletsStateHolder.userWalletsListManager?.asLockable(),
|
||||
raise = {
|
||||
UnlockWalletsError.DataError(
|
||||
cause = IllegalStateException("The lockable user wallets list manager could not be found"),
|
||||
)
|
||||
},
|
||||
)
|
||||
suspend operator fun invoke(type: UnlockType = UnlockType.ANY): Either<UnlockWalletsError, Unit> = either {
|
||||
val userWalletsListManager = ensureNotNull(
|
||||
value = walletsStateHolder.userWalletsListManager?.asLockable(),
|
||||
raise = {
|
||||
UnlockWalletsError.DataError(
|
||||
cause = IllegalStateException("The lockable user wallets list manager could not be found"),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
userWalletsListManager.unlock(throwIfNotAllWalletsUnlocked)
|
||||
.doOnFailure { error ->
|
||||
val e = when (error) {
|
||||
is UserWalletsListError.NoUserWalletSelected -> UnlockWalletsError.NoUserWalletSelected
|
||||
is UserWalletsListError.NotAllUserWalletsUnlocked ->
|
||||
UnlockWalletsError.NotAllUserWalletsUnlocked
|
||||
else -> UnlockWalletsError.UnableToUnlockWallets
|
||||
}
|
||||
|
||||
raise(e)
|
||||
userWalletsListManager.unlock(type)
|
||||
.doOnFailure { error ->
|
||||
val e = when (error) {
|
||||
is UserWalletsListError.NoUserWalletSelected -> UnlockWalletsError.NoUserWalletSelected
|
||||
is UserWalletsListError.NotAllUserWalletsUnlocked ->
|
||||
UnlockWalletsError.NotAllUserWalletsUnlocked
|
||||
else -> UnlockWalletsError.UnableToUnlockWallets
|
||||
}
|
||||
}
|
||||
|
||||
raise(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ internal class ExchangeStatusConverter : Converter<ExchangeStatusResponse, Excha
|
|||
},
|
||||
txId = value.externalTxId,
|
||||
txExternalUrl = value.externalTxUrl,
|
||||
txExternalId = value.externalTxId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1480,7 +1480,16 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
fromTokenStatus.currency.network.derivationPath.value,
|
||||
)
|
||||
nativeTokenBalance?.let { balance ->
|
||||
if (balance.value.minus(spendAmount.value) > fee.multiply(percentsToFeeIncrease)) {
|
||||
val balanceToCheck = when (fromTokenStatus.currency) {
|
||||
is CryptoCurrency.Token -> {
|
||||
balance.value
|
||||
}
|
||||
is CryptoCurrency.Coin -> {
|
||||
// need to check balance minus amount only if amount to swap in native token
|
||||
balance.value.minus(spendAmount.value)
|
||||
}
|
||||
}
|
||||
if (balanceToCheck > fee.multiply(percentsToFeeIncrease)) {
|
||||
SwapFeeState.Enough
|
||||
} else {
|
||||
val nativeToken = getNativeToken(fromTokenStatus.currency.network.backendId)
|
||||
|
|
@ -1510,9 +1519,9 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
} else {
|
||||
val token = currenciesRepository
|
||||
.getMultiCurrencyWalletCurrenciesSync(userWalletId)
|
||||
.filterIsInstance<CryptoCurrency.Token>()
|
||||
.find {
|
||||
it is CryptoCurrency.Token &&
|
||||
it.contractAddress.equals(feePaidCurrency.contractAddress, ignoreCase = true) &&
|
||||
it.contractAddress.equals(feePaidCurrency.contractAddress, ignoreCase = true) &&
|
||||
it.network.derivationPath == fromTokenStatus.currency.network.derivationPath
|
||||
}
|
||||
SwapFeeState.NotEnough(
|
||||
|
|
|
|||
|
|
@ -32,19 +32,13 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
|
||||
data class Locked(
|
||||
override val walletCardState: WalletCardState,
|
||||
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val onUnlockNotificationClick: () -> Unit,
|
||||
val isBottomSheetShow: Boolean = false,
|
||||
val onBottomSheetDismiss: () -> Unit = {},
|
||||
val onUnlockClick: () -> Unit,
|
||||
val onScanClick: () -> Unit,
|
||||
) : MultiCurrency(),
|
||||
WalletStateHolder by LockedWalletStateHolder(
|
||||
walletCardState,
|
||||
bottomSheetConfig,
|
||||
onUnlockNotificationClick,
|
||||
isBottomSheetShow,
|
||||
onBottomSheetDismiss,
|
||||
onUnlockClick,
|
||||
onScanClick,
|
||||
) {
|
||||
|
||||
override val tokensListState = WalletTokensListState.ContentState.Locked
|
||||
|
|
@ -70,21 +64,15 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
data class Locked(
|
||||
override val walletCardState: WalletCardState,
|
||||
override val buttons: PersistentList<WalletManageButton>,
|
||||
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val onUnlockNotificationClick: () -> Unit,
|
||||
val isBottomSheetShow: Boolean = false,
|
||||
val onBottomSheetDismiss: () -> Unit = {},
|
||||
val onUnlockClick: () -> Unit,
|
||||
val onScanClick: () -> Unit,
|
||||
val onExploreClick: () -> Unit,
|
||||
) : SingleCurrency(),
|
||||
TxHistoryStateHolder by LockedTxHistoryStateHolder(onExploreClick),
|
||||
WalletStateHolder by LockedWalletStateHolder(
|
||||
walletCardState,
|
||||
bottomSheetConfig,
|
||||
onUnlockNotificationClick,
|
||||
isBottomSheetShow,
|
||||
onBottomSheetDismiss,
|
||||
onUnlockClick,
|
||||
onScanClick,
|
||||
) {
|
||||
|
||||
override val marketPriceBlockState: MarketPriceBlockState? = null
|
||||
|
|
@ -108,20 +96,14 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
data class Locked(
|
||||
override val walletCardState: WalletCardState,
|
||||
val onUnlockNotificationClick: () -> Unit,
|
||||
val isBottomSheetShow: Boolean = false,
|
||||
val onBottomSheetDismiss: () -> Unit = {},
|
||||
val onUnlockClick: () -> Unit,
|
||||
val onScanClick: () -> Unit,
|
||||
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val onExploreClick: () -> Unit,
|
||||
) : Visa(),
|
||||
TxHistoryStateHolder by LockedTxHistoryStateHolder(onExploreClick),
|
||||
WalletStateHolder by LockedWalletStateHolder(
|
||||
walletCardState,
|
||||
bottomSheetConfig,
|
||||
onUnlockNotificationClick,
|
||||
isBottomSheetShow,
|
||||
onBottomSheetDismiss,
|
||||
onUnlockClick,
|
||||
onScanClick,
|
||||
) {
|
||||
|
||||
override val balancesAndLimitBlockState: BalancesAndLimitsBlockState? = null
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model.holder
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletPullToRefreshConfig
|
||||
|
|
@ -18,11 +17,8 @@ internal interface WalletStateHolder {
|
|||
|
||||
internal class LockedWalletStateHolder(
|
||||
override val walletCardState: WalletCardState,
|
||||
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
onUnlockNotificationClick: () -> Unit,
|
||||
isBottomSheetShow: Boolean,
|
||||
onBottomSheetDismiss: () -> Unit,
|
||||
onUnlockClick: () -> Unit,
|
||||
onScanClick: () -> Unit,
|
||||
) : WalletStateHolder {
|
||||
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig
|
||||
|
|
@ -31,13 +27,4 @@ internal class LockedWalletStateHolder(
|
|||
override val warnings: ImmutableList<WalletNotification> = persistentListOf(
|
||||
WalletNotification.UnlockWallets(onUnlockNotificationClick),
|
||||
)
|
||||
|
||||
override val bottomSheetConfig = TangemBottomSheetConfig(
|
||||
isShow = isBottomSheetShow,
|
||||
onDismissRequest = onBottomSheetDismiss,
|
||||
content = WalletBottomSheetConfig.UnlockWallets(
|
||||
onUnlockClick = onUnlockClick,
|
||||
onScanClick = onScanClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -7,18 +7,28 @@ internal class CloseBottomSheetTransformer(userWalletId: UserWalletId) : WalletS
|
|||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(bottomSheetConfig = prevState.bottomSheetConfig?.copy(isShow = false))
|
||||
}
|
||||
is WalletState.MultiCurrency.Locked -> prevState.copy(isBottomSheetShow = false)
|
||||
is WalletState.SingleCurrency.Content -> {
|
||||
prevState.copy(bottomSheetConfig = prevState.bottomSheetConfig?.copy(isShow = false))
|
||||
}
|
||||
is WalletState.SingleCurrency.Locked -> prevState.copy(isBottomSheetShow = false)
|
||||
is WalletState.Visa.Content -> prevState.copy(
|
||||
bottomSheetConfig = prevState.bottomSheetConfig?.copy(isShow = false),
|
||||
is WalletState.MultiCurrency.Content -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.MultiCurrency.Locked -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.SingleCurrency.Content -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.SingleCurrency.Locked -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.Visa.Content -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.Visa.Locked -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(prevState),
|
||||
)
|
||||
is WalletState.Visa.Locked -> prevState.copy(isBottomSheetShow = false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateConfig(prevState: WalletState) = prevState.bottomSheetConfig?.copy(
|
||||
isShow = false,
|
||||
)
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
|
||||
internal class InitializeWalletsTransformer(
|
||||
private val selectedWalletIndex: Int,
|
||||
private val selectedWallet: UserWallet,
|
||||
private val wallets: List<UserWallet>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
|
@ -23,7 +22,7 @@ internal class InitializeWalletsTransformer(
|
|||
override fun transform(prevState: WalletScreenState): WalletScreenState {
|
||||
return prevState.copy(
|
||||
onBackClick = clickIntents::onBackClick,
|
||||
topBarConfig = createTopBarConfig(userWallet = selectedWallet),
|
||||
topBarConfig = createTopBarConfig(),
|
||||
selectedWalletIndex = selectedWalletIndex,
|
||||
wallets = wallets
|
||||
.map { userWallet ->
|
||||
|
|
@ -38,13 +37,9 @@ internal class InitializeWalletsTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createTopBarConfig(userWallet: UserWallet): WalletTopBarConfig {
|
||||
private fun createTopBarConfig(): WalletTopBarConfig {
|
||||
return WalletTopBarConfig(
|
||||
onDetailsClick = if (userWallet.isLocked) {
|
||||
clickIntents::onOpenUnlockWalletsBottomSheetClick
|
||||
} else {
|
||||
clickIntents::onDetailsClick
|
||||
},
|
||||
onDetailsClick = clickIntents::onDetailsClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -53,27 +48,24 @@ internal class InitializeWalletsTransformer(
|
|||
multiCurrencyCreator = {
|
||||
WalletState.MultiCurrency.Locked(
|
||||
walletCardState = userWallet.toLockedWalletCardState(),
|
||||
bottomSheetConfig = null,
|
||||
onUnlockNotificationClick = clickIntents::onOpenUnlockWalletsBottomSheetClick,
|
||||
onUnlockClick = clickIntents::onUnlockWalletClick,
|
||||
onScanClick = clickIntents::onScanToUnlockWalletClick,
|
||||
)
|
||||
},
|
||||
singleCurrencyCreator = {
|
||||
WalletState.SingleCurrency.Locked(
|
||||
walletCardState = userWallet.toLockedWalletCardState(),
|
||||
bottomSheetConfig = null,
|
||||
buttons = createDisabledButtons(),
|
||||
onUnlockNotificationClick = clickIntents::onOpenUnlockWalletsBottomSheetClick,
|
||||
onUnlockClick = clickIntents::onUnlockWalletClick,
|
||||
onScanClick = clickIntents::onScanToUnlockWalletClick,
|
||||
onExploreClick = clickIntents::onExploreClick,
|
||||
)
|
||||
},
|
||||
visaWalletCreator = {
|
||||
WalletState.Visa.Locked(
|
||||
walletCardState = userWallet.toLockedWalletCardState(),
|
||||
bottomSheetConfig = null,
|
||||
onUnlockNotificationClick = clickIntents::onOpenUnlockWalletsBottomSheetClick,
|
||||
onUnlockClick = clickIntents::onUnlockWalletClick,
|
||||
onScanClick = clickIntents::onScanToUnlockWalletClick,
|
||||
onExploreClick = clickIntents::onExploreClick,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,41 +13,30 @@ internal class OpenBottomSheetTransformer(
|
|||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(
|
||||
bottomSheetConfig = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = onDismissBottomSheet,
|
||||
content = content,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletState.MultiCurrency.Locked -> {
|
||||
prevState.copy(isBottomSheetShow = true, onBottomSheetDismiss = onDismissBottomSheet)
|
||||
}
|
||||
is WalletState.SingleCurrency.Content -> {
|
||||
prevState.copy(
|
||||
bottomSheetConfig = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = onDismissBottomSheet,
|
||||
content = content,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
prevState.copy(isBottomSheetShow = true, onBottomSheetDismiss = onDismissBottomSheet)
|
||||
}
|
||||
is WalletState.MultiCurrency.Content -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
is WalletState.MultiCurrency.Locked -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
is WalletState.SingleCurrency.Content -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
is WalletState.SingleCurrency.Locked -> prevState.copy(
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
is WalletState.Visa.Content -> prevState.copy(
|
||||
bottomSheetConfig = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = onDismissBottomSheet,
|
||||
content = content,
|
||||
),
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
is WalletState.Visa.Locked -> prevState.copy(
|
||||
isBottomSheetShow = true,
|
||||
onBottomSheetDismiss = onDismissBottomSheet,
|
||||
bottomSheetConfig = updateConfig(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateConfig() = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = onDismissBottomSheet,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -19,7 +18,6 @@ internal class UnlockWalletTransformer(
|
|||
|
||||
override fun transform(prevState: WalletScreenState): WalletScreenState {
|
||||
return prevState.copy(
|
||||
topBarConfig = prevState.topBarConfig.toUnlockedState(),
|
||||
wallets = prevState.wallets
|
||||
.map { state ->
|
||||
val unlockedWallet = getUnlockedWallet(state.walletCardState.id)
|
||||
|
|
@ -29,10 +27,6 @@ internal class UnlockWalletTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun WalletTopBarConfig.toUnlockedState(): WalletTopBarConfig {
|
||||
return copy(onDetailsClick = clickIntents::onDetailsClick)
|
||||
}
|
||||
|
||||
private fun getUnlockedWallet(walletId: UserWalletId): UserWallet? {
|
||||
return unlockedWallets.firstOrNull { it.walletId == walletId }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.tokens.model.TokenActionsState
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletCurrencyActionsClickIntentsImplementor
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletCurrencyActionsClickIntents
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -16,7 +16,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
|
||||
internal class MultiWalletCurrencyActionsConverter(
|
||||
private val userWallet: UserWallet,
|
||||
private val clickIntents: WalletCurrencyActionsClickIntentsImplementor,
|
||||
private val clickIntents: WalletCurrencyActionsClickIntents,
|
||||
) : Converter<TokenActionsState, ImmutableList<TokenActionButtonConfig>> {
|
||||
|
||||
override fun convert(value: TokenActionsState): ImmutableList<TokenActionButtonConfig> {
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ internal class WalletViewModel @Inject constructor(
|
|||
stateHolder.update(
|
||||
transformer = InitializeWalletsTransformer(
|
||||
selectedWalletIndex = action.selectedWalletIndex,
|
||||
selectedWallet = action.selectedWallet,
|
||||
wallets = action.wallets,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import javax.inject.Inject
|
|||
@ViewModelScoped
|
||||
internal class WalletClickIntents @Inject constructor(
|
||||
private val walletCardClickIntentsImplementor: WalletCardClickIntentsImplementor,
|
||||
private val warningsClickIntentsImplementer: WalletWarningsClickIntentsImplementer,
|
||||
private val warningsClickIntentsImplementer: WalletWarningsClickIntentsImplementor,
|
||||
private val currencyActionsClickIntentsImplementor: WalletCurrencyActionsClickIntentsImplementor,
|
||||
private val contentClickIntentsImplementor: WalletContentClickIntentsImplementor,
|
||||
private val visaWalletIntentsImplementor: VisaWalletIntentsImplementor,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.viewmodels.intents
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
|
|
@ -9,17 +10,19 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.PortfolioEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.ActionsBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCurrencyActionsConverter
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface WalletContentClickIntents {
|
||||
|
|
@ -43,8 +46,9 @@ internal interface WalletContentClickIntents {
|
|||
@ViewModelScoped
|
||||
internal class WalletContentClickIntentsImplementor @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val currencyActionsClickIntentsImplementor: WalletCurrencyActionsClickIntentsImplementor,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val currencyActionsClickIntents: WalletCurrencyActionsClickIntentsImplementor,
|
||||
private val walletWarningsClickIntents: WalletWarningsClickIntentsImplementor,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
|
|
@ -55,7 +59,33 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onBackClick() = router.popBackStack()
|
||||
|
||||
override fun onDetailsClick() = router.openDetailsScreen()
|
||||
override fun onDetailsClick() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $it
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (userWallet.isLocked) {
|
||||
stateHolder.showBottomSheet(
|
||||
WalletBottomSheetConfig.UnlockWallets(
|
||||
onUnlockClick = walletWarningsClickIntents::onUnlockWalletClick,
|
||||
onScanClick = walletWarningsClickIntents::onScanToUnlockWalletClick,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
router.openDetailsScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onManageTokensClick() {
|
||||
analyticsEventHandler.send(PortfolioEvent.ButtonManageTokens)
|
||||
|
|
@ -74,9 +104,20 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $it
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return@launch
|
||||
}
|
||||
|
||||
getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = cryptoCurrencyStatus)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
|
|
@ -90,7 +131,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
ActionsBottomSheetConfig(
|
||||
actions = MultiWalletCurrencyActionsConverter(
|
||||
userWallet = userWallet,
|
||||
clickIntents = currencyActionsClickIntentsImplementor,
|
||||
clickIntents = currencyActionsClickIntents,
|
||||
).convert(tokenActionsState),
|
||||
),
|
||||
userWallet.walletId,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.viewmodels.intents
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
|
|
@ -12,17 +13,19 @@ import com.tangem.domain.settings.RemindToRateAppLaterUseCase
|
|||
import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.models.UnlockWalletsError
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.ScanCardToUnlockWalletClickHandler
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.ScanCardToUnlockWalletError
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
|
|
@ -57,17 +60,17 @@ internal interface WalletWarningsClickIntents {
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
@ViewModelScoped
|
||||
internal class WalletWarningsClickIntentsImplementer @Inject constructor(
|
||||
internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val walletEventSender: WalletEventSender,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val unlockWalletsUseCase: UnlockWalletsUseCase,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val scanCardToUnlockWalletClickHandler: ScanCardToUnlockWalletClickHandler,
|
||||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val setCardWasScannedUseCase: SetCardWasScannedUseCase,
|
||||
private val neverToSuggestRateAppUseCase: NeverToSuggestRateAppUseCase,
|
||||
private val remindToRateAppLaterUseCase: RemindToRateAppLaterUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val scanCardToUnlockWalletClickHandler: ScanCardToUnlockWalletClickHandler,
|
||||
private val unlockWalletsUseCase: UnlockWalletsUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -82,31 +85,33 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor(
|
|||
}
|
||||
|
||||
private fun prepareOnboardingProcess() {
|
||||
getSelectedWalletSyncUseCase.unwrap()?.let {
|
||||
reduxStateHolder.dispatch(
|
||||
LegacyAction.StartOnboardingProcess(
|
||||
scanResponse = it.scanResponse,
|
||||
canSkipBackup = false,
|
||||
),
|
||||
)
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
getSelectedUserWallet()?.let {
|
||||
reduxStateHolder.dispatch(
|
||||
LegacyAction.StartOnboardingProcess(
|
||||
scanResponse = it.scanResponse,
|
||||
canSkipBackup = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCloseAlreadySignedHashesWarningClick() {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val userWallet = getSelectedUserWallet() ?: return@launch
|
||||
|
||||
setCardWasScannedUseCase(cardId = userWallet.cardId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGenerateMissedAddressesClick(missedAddressCurrencies: List<CryptoCurrency>) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
analyticsEventHandler.send(Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main))
|
||||
analyticsEventHandler.send(MainScreen.NoticeScanYourCardTapped)
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val userWallet = getSelectedUserWallet() ?: return@launch
|
||||
|
||||
derivePublicKeysUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currencies = missedAddressCurrencies,
|
||||
|
|
@ -119,18 +124,19 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor(
|
|||
override fun onOpenUnlockWalletsBottomSheetClick() {
|
||||
analyticsEventHandler.send(MainScreen.WalletUnlockTapped)
|
||||
|
||||
val config = requireNotNull(stateHolder.getSelectedWallet().bottomSheetConfig) {
|
||||
"Impossible to open unlock wallet bottom sheet if it's null"
|
||||
}
|
||||
|
||||
stateHolder.showBottomSheet(config.content)
|
||||
stateHolder.showBottomSheet(
|
||||
WalletBottomSheetConfig.UnlockWallets(
|
||||
onUnlockClick = this::onUnlockWalletClick,
|
||||
onScanClick = this::onScanToUnlockWalletClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onUnlockWalletClick() {
|
||||
analyticsEventHandler.send(MainScreen.UnlockAllWithBiometrics)
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
unlockWalletsUseCase(throwIfNotAllWalletsUnlocked = true)
|
||||
unlockWalletsUseCase(type = UnlockType.ALL_WITHOUT_SELECT)
|
||||
.onRight { stateHolder.update(CloseBottomSheetTransformer(stateHolder.getSelectedWalletId())) }
|
||||
.onLeft(::handleUnlockWalletsError)
|
||||
}
|
||||
|
|
@ -204,4 +210,19 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor(
|
|||
shouldShowSwapPromoWalletUseCase.neverToShow()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSelectedUserWallet(): UserWallet? {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
return getUserWalletUseCase(userWalletId).getOrElse {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $it
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +85,9 @@ web3j = "4.10.1"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "release-app_5.8-529"
|
||||
tangemBlockchainSdk = "release-app_5.8-533"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "release-app_5.8-335"
|
||||
tangemCardSdk = "release-app_5.8-336"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
# endregion Tangem
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue