Updated on 2026-08-14

This commit is contained in:
Tangem 2025-07-16 13:17:41 +04:00
parent 3da8569ae6
commit 352ae036f3
2 changed files with 69 additions and 58 deletions

View file

@ -34,36 +34,33 @@ class SaveManagedTokensUseCase(
currenciesToAdd: Map<ManagedCryptoCurrency.Token, Set<Network>>,
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
): Either<Throwable, Unit> = Either.catch {
val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId)
val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId)
if (currenciesToRemove.isNotEmpty()) {
val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId)
derivationsRepository.derivePublicKeysByNetworks(
userWalletId = userWalletId,
networks = currenciesToAdd.values.flatten(),
)
currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = removingCurrencies)
val existingCurrencies = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
removeCurrenciesFromWalletManager(userWalletId = userWalletId, currencies = removingCurrencies)
}
val newCurrenciesList = existingCurrencies
.filterNot(removingCurrencies::contains)
.toMutableList()
.also { it.addAll(addingCurrencies) }
if (currenciesToAdd.isNotEmpty()) {
derivationsRepository.derivePublicKeysByNetworks(
userWalletId = userWalletId,
networks = currenciesToAdd.values.flatten(),
)
currenciesRepository.saveNewCurrenciesList(userWalletId, newCurrenciesList)
val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId)
removeCurrenciesFromWalletManager(
userWalletId = userWalletId,
currencies = removingCurrencies.filterNot(existingCurrencies::contains),
)
refreshUpdatedNetworks(
userWalletId = userWalletId,
existingCurrencies = existingCurrencies,
currenciesToAdd = addingCurrencies,
)
val savedCurrencies = currenciesRepository.addCurrencies(
userWalletId = userWalletId,
currencies = addingCurrencies,
)
refreshUpdatedYieldBalances(userWalletId, existingCurrencies)
refreshUpdatedNetworks(userWalletId = userWalletId, addedCurrencies = savedCurrencies)
refreshUpdatedQuotes(addingCurrencies)
refreshUpdatedYieldBalances(userWalletId = userWalletId, addedCurrencies = savedCurrencies)
refreshUpdatedQuotes(addedCurrencies = savedCurrencies)
}
}
private suspend fun removeCurrenciesFromWalletManager(
@ -83,43 +80,30 @@ class SaveManagedTokensUseCase(
)
}
private suspend fun refreshUpdatedNetworks(
userWalletId: UserWalletId,
currenciesToAdd: List<CryptoCurrency>,
existingCurrencies: List<CryptoCurrency>,
) {
val networksToUpdate = currenciesToAdd
.asSequence()
.filterIsInstance<CryptoCurrency.Token>()
.map(CryptoCurrency.Token::network)
.filterTo(hashSetOf()) { hasCoinForNetwork(existingCurrencies, it) }
val networkToUpdate = currenciesToAdd.map { it.network }
.subtract(existingCurrencies.map { it.network }.toSet())
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
multiNetworkStatusFetcher(
MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
),
)
}
private suspend fun refreshUpdatedYieldBalances(
userWalletId: UserWalletId,
existingCurrencies: List<CryptoCurrency>,
addedCurrencies: List<CryptoCurrency>,
) {
if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) {
multiYieldBalanceFetcher(
params = MultiYieldBalanceFetcher.Params(
userWalletId = userWalletId,
currencyIdWithNetworkMap = existingCurrencies.associateTo(hashMapOf()) { it.id to it.network },
currencyIdWithNetworkMap = addedCurrencies.associateTo(hashMapOf()) { it.id to it.network },
),
)
} else {
stakingRepository.fetchMultiYieldBalance(
userWalletId = userWalletId,
cryptoCurrencies = existingCurrencies,
cryptoCurrencies = addedCurrencies,
refresh = true,
)
}
@ -134,16 +118,6 @@ class SaveManagedTokensUseCase(
)
}
/**
* Determines if the [existingCurrencies] list contains a coin that corresponds
* to the given [network].
*/
private fun hasCoinForNetwork(existingCurrencies: List<CryptoCurrency>, network: Network): Boolean {
return existingCurrencies.any { currency ->
currency is CryptoCurrency.Coin && currency.network == network
}
}
private suspend fun Map<ManagedCryptoCurrency.Token, Set<Network>>.mapToCryptoCurrencies(
userWalletId: UserWalletId,
): List<CryptoCurrency> {

View file

@ -18,12 +18,15 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.settings.NeverToSuggestRateAppUseCase
import com.tangem.domain.settings.RemindToRateAppLaterUseCase
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
import com.tangem.domain.wallets.models.UnlockWalletsError
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
@ -40,6 +43,9 @@ 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
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@ -103,6 +109,8 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
private val urlOpener: UrlOpener,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val appRouter: AppRouter,
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
@ -146,13 +154,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
).fold(
ifLeft = { Timber.e(it, "Failed to derive public keys") },
ifRight = {
multiNetworkStatusFetcher(
params = MultiNetworkStatusFetcher.Params(
userWalletId = userWallet.walletId,
networks = missedAddressCurrencies.map(CryptoCurrency::network).toSet(),
),
)
.onLeft { Timber.e("Unable to refresh token list: $it") }
fetchCryptoCurrencies(userWalletId = userWallet.walletId, currencies = missedAddressCurrencies)
},
)
}
@ -369,6 +371,41 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
}
private suspend fun fetchCryptoCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
coroutineScope {
listOf(
async {
multiNetworkStatusFetcher(
params = MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = currencies.map(CryptoCurrency::network).toSet(),
),
)
.onLeft { Timber.e("Unable to fetch networks: $it") }
},
async {
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = currencies.mapNotNull { it.id.rawCurrencyId }.toSet(),
appCurrencyId = null,
),
)
.onLeft { Timber.e("Unable to fetch quotes: $it") }
},
async {
multiYieldBalanceFetcher(
params = MultiYieldBalanceFetcher.Params(
userWalletId = userWalletId,
currencyIdWithNetworkMap = currencies.associate { it.id to it.network },
),
)
.onLeft { Timber.e("Unable to fetch yield balances: $it") }
},
)
.awaitAll()
}
}
private fun getSelectedUserWallet(): UserWallet? {
val userWalletId = stateHolder.getSelectedWalletId()
return getUserWalletUseCase(userWalletId).getOrElse {