Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-25 17:03:24 +04:00
parent 504d0276f9
commit d6fbc592c3
11 changed files with 120 additions and 18 deletions

View file

@ -36,19 +36,28 @@ class AdditionalFeedbackInfo {
var userWalletId: String = ""
// wallets
internal val walletsInfo = mutableListOf<EmailWalletInfo>()
internal var onSendErrorWalletInfo: EmailWalletInfo? = null
var walletsInfo = emptyList<EmailWalletInfo>()
private set
var onSendErrorWalletInfo: EmailWalletInfo? = null
private set
var signedHashesCount: String = ""
private set
// device
var phoneModel: String = Build.MODEL
private set
var osVersion: String = Build.VERSION.SDK_INT.toString()
private set
// send error
var destinationAddress: String = ""
private set
var amount: String = ""
private set
var fee: String = ""
private set
var token: String = ""
private set
private val Address.name: String
get() = type.javaClass.simpleName
@ -65,10 +74,7 @@ class AdditionalFeedbackInfo {
@Deprecated("Don't use it directly")
fun setWalletsInfo(walletManagers: List<WalletManager>) {
walletsInfo.clear()
walletManagers.forEach { manager ->
walletsInfo.add(createEmailWalletInfo(manager))
}
walletsInfo = walletManagers.map(::createEmailWalletInfo)
}
fun updateOnSendError(

View file

@ -176,6 +176,8 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
walletCurrenciesManager.addListener(action.topUpController)
}
is GlobalAction.UpdateUserWalletsListManager -> {
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
/*
* If implementation of the UserWalletsListManager is changed,
* then all observers of selectedUserWallet become irrelevant.
@ -183,13 +185,13 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
action.manager.selectedUserWallet
.distinctUntilChanged()
.onEach { userWallet ->
Analytics.send(event = Basic.WalletOpened())
Analytics.send(Basic.WalletOpened())
store.state.globalState.feedbackManager?.infoHolder?.let { infoHolder ->
infoHolder.setCardInfo(data = userWallet.scanResponse)
infoHolder.setCardInfo(userWallet.scanResponse)
store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
.getAll(userWalletId = userWallet.walletId)
walletManagersFacade
.getAll(userWallet.walletId)
.onEach(infoHolder::setWalletsInfo)
.launchIn(scope)
}

View file

@ -63,9 +63,9 @@ internal object TokensDomainModule {
@ViewModelScoped
fun provideRemoveCurrencyUseCase(
currenciesRepository: CurrenciesRepository,
dispatchers: CoroutineDispatcherProvider,
walletManagersFacade: WalletManagersFacade,
): RemoveCurrencyUseCase {
return RemoveCurrencyUseCase(currenciesRepository, dispatchers)
return RemoveCurrencyUseCase(currenciesRepository, walletManagersFacade)
}
@Provides

View file

@ -403,7 +403,19 @@ object TokensMiddleware {
private suspend fun removeNewCurrenciesIfNeeded(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
if (currencies.isEmpty()) return
val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository)
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = currencies)
walletManagersFacade.remove(
userWalletId = userWalletId,
networks = currencies
.filterIsInstance<CryptoCurrency.Coin>()
.mapTo(hashSetOf(), CryptoCurrency::network),
)
walletManagersFacade.removeTokens(
userWalletId = userWalletId,
tokens = currencies.filterIsInstance<CryptoCurrency.Token>().toSet(),
)
}
}

View file

@ -6,6 +6,7 @@ import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.extensions.addOrReplace
import com.tangem.utils.extensions.removeBy
import kotlinx.coroutines.flow.Flow
internal class DefaultWalletManagersStore(
@ -43,10 +44,18 @@ internal class DefaultWalletManagersStore(
val updatedWalletManagers = walletManagers
?.addOrReplace(walletManager) {
it.wallet.blockchain == walletManager.wallet.blockchain &&
it.wallet.publicKey == walletManager.wallet.publicKey
it.wallet.publicKey.derivationPath == walletManager.wallet.publicKey.derivationPath
}
?: listOf(walletManager)
store(userWalletId, updatedWalletManagers)
}
override suspend fun remove(userWalletId: UserWalletId, predicate: (WalletManager) -> Boolean) {
val walletManagers = getSyncOrNull(userWalletId)?.toMutableList() ?: return
walletManagers.removeBy(predicate)
store(userWalletId, walletManagers)
}
}

View file

@ -19,5 +19,7 @@ interface WalletManagersStore {
suspend fun store(userWalletId: UserWalletId, walletManager: WalletManager)
suspend fun remove(userWalletId: UserWalletId, predicate: (WalletManager) -> Boolean)
suspend fun clear()
}

View file

@ -1,7 +1,7 @@
package com.tangem.utils.extensions
/**
* Removes an element from the collection based on the provided predicate.
* Removes elements from the collection based on the provided predicate.
*
* !!!This function is not thread-safe!!!
*

View file

@ -60,6 +60,50 @@ class DefaultWalletManagersFacade(
return getAndUpdateWalletManager(userWallet, blockchain, derivationPath, extraTokens)
}
override suspend fun remove(userWalletId: UserWalletId, networks: Set<Network>) {
if (networks.isEmpty()) return
val blockchainsToDerivationPaths = networks.map {
Blockchain.fromId(it.id.value) to it.derivationPath.value
}
walletManagersStore.remove(userWalletId) { walletManager ->
val wallet = walletManager.wallet
val blockchainToDerivationPath = wallet.blockchain to wallet.publicKey.derivationPath?.rawPath
blockchainToDerivationPath in blockchainsToDerivationPaths
}
}
override suspend fun removeTokens(userWalletId: UserWalletId, tokens: Set<CryptoCurrency.Token>) {
if (tokens.isEmpty()) return
tokens
.groupBy(CryptoCurrency.Token::network)
.forEach { (network, networkTokens) ->
removeTokens(userWalletId, network, networkTokens)
}
}
private suspend fun removeTokens(
userWalletId: UserWalletId,
network: Network,
networkTokens: List<CryptoCurrency.Token>,
) {
val walletManager = walletManagersStore.getSyncOrNull(
userWalletId = userWalletId,
blockchain = Blockchain.fromId(network.id.value),
derivationPath = network.derivationPath.value,
) ?: return
val tokensToRemove = sdkTokenConverter.convertList(networkTokens)
tokensToRemove.forEach { token ->
walletManager.removeToken(token)
}
walletManagersStore.store(userWalletId, walletManager)
}
override suspend fun updatePendingTransactions(
userWalletId: UserWalletId,
network: Network,

View file

@ -37,6 +37,16 @@ interface WalletManagersFacade {
extraTokens: Set<CryptoCurrency.Token>,
): UpdateWalletManagerResult
/**
* Removes the wallet managers associated with a user's wallet and networks.
*
* @param userWalletId The ID of the user's wallet.
* @param networks Set of networks
* */
suspend fun remove(userWalletId: UserWalletId, networks: Set<Network>)
suspend fun removeTokens(userWalletId: UserWalletId, tokens: Set<CryptoCurrency.Token>)
/**
* Returns [UpdateWalletManagerResult] with last pending transactions
*

View file

@ -2,4 +2,6 @@ package com.tangem.domain.tokens.model.remove
sealed class RemoveCurrencyError : Throwable() {
data class DataError(override val cause: Throwable) : RemoveCurrencyError()
object HasLinkedTokens : RemoveCurrencyError()
}

View file

@ -6,12 +6,12 @@ import arrow.core.raise.either
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.remove.RemoveCurrencyError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
class RemoveCurrencyUseCase(
internal val currenciesRepository: CurrenciesRepository,
internal val dispatchers: CoroutineDispatcherProvider,
private val currenciesRepository: CurrenciesRepository,
private val walletManagersFacade: WalletManagersFacade,
) {
suspend operator fun invoke(
@ -19,8 +19,23 @@ class RemoveCurrencyUseCase(
currency: CryptoCurrency,
): Either<RemoveCurrencyError, Unit> {
return either {
if (hasLinkedTokens(userWalletId, currency)) {
raise(RemoveCurrencyError.HasLinkedTokens)
}
catch(
block = { currenciesRepository.removeCurrency(userWalletId, currency) },
block = {
currenciesRepository.removeCurrency(userWalletId, currency)
when (currency) {
is CryptoCurrency.Coin -> {
walletManagersFacade.remove(userWalletId, setOf(currency.network))
}
is CryptoCurrency.Token -> {
walletManagersFacade.removeTokens(userWalletId, setOf(currency))
}
}
},
catch = { raise(RemoveCurrencyError.DataError(it)) },
)
}