diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt index a5eb111a0d..18e689e141 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt @@ -79,12 +79,11 @@ internal class ManagedCryptoCurrencyFactory { scanResponse: ScanResponse, ): List = tokensResponse.tokens .mapNotNull { token -> - maybeCreateCustomToken(token, null, scanResponse) + maybeCreateCustomToken(token, scanResponse) } private fun maybeCreateCustomToken( token: UserTokensResponse.Token, - imageHost: String?, scanResponse: ScanResponse, ): ManagedCryptoCurrency? { val blockchain = Blockchain.fromNetworkId(token.networkId) @@ -107,7 +106,7 @@ internal class ManagedCryptoCurrencyFactory { currencyId = getCoinId(network, blockchain.toCoinId()), name = token.name, symbol = token.symbol, - iconUrl = getIconUrl(blockchain.id, imageHost), + iconUrl = getIconUrl(blockchain.id), network = network, ) } else { @@ -115,7 +114,7 @@ internal class ManagedCryptoCurrencyFactory { currencyId = getTokenId(network, token.id, contractAddress), name = token.name, symbol = token.symbol, - iconUrl = token.id?.let { getIconUrl(it, imageHost) }, + iconUrl = token.id?.let { getIconUrl(it) }, contractAddress = contractAddress, network = network, decimals = token.decimals, diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index 1d25e1ea81..0c95de24ce 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -76,54 +76,39 @@ internal class DefaultCurrenciesRepository( } override suspend fun saveNewCurrenciesList(userWalletId: UserWalletId, currencies: List) { - val savedResponse = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { "Saved tokens empty. Can not perform add currencies action" }, - ) - val newCoins = createCoinsForNewTokenList( - userWalletId = userWalletId, - newTokens = currencies.filterIsInstance(), - ) - val newCurrencies = (newCoins + currencies).distinct() - val updatedResponse = savedResponse.copy( - tokens = newCurrencies.map(userTokensResponseFactory::createResponseToken), - ) - storeAndPushTokens( - userWalletId = userWalletId, - response = updatedResponse, - ) - fetchExchangeableUserMarketCoinsByIds(userWalletId, updatedResponse) + withContext(dispatchers.io) { + val savedResponse = requireNotNull( + value = getSavedUserTokensResponseSync(key = userWalletId), + lazyMessage = { "Saved tokens empty. Can not perform add currencies action." }, + ) + + val newCurrencies = populateCurrenciesWithMissedCoins(currencies) + + val updatedResponse = savedResponse.copy( + tokens = newCurrencies.map(userTokensResponseFactory::createResponseToken), + ) + storeAndPushTokens( + userWalletId = userWalletId, + response = updatedResponse, + ) + + fetchExchangeableUserMarketCoinsByIds(userWalletId, updatedResponse) + } } override suspend fun addCurrencies(userWalletId: UserWalletId, currencies: List) { - return withContext(dispatchers.io) { + withContext(dispatchers.io) { val savedCurrencies = requireNotNull( value = getSavedUserTokensResponseSync(key = userWalletId), lazyMessage = { "Saved tokens empty. Can not perform add currencies action" }, ) - val filteredCurrencies = currencies.toMutableList() - filteredCurrencies.filterNot { currency -> - val blockchain = getBlockchain(networkId = currency.network.id) - val networkId = blockchain.toNetworkId() - val contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress - savedCurrencies.tokens.firstOrNull { token -> - token.contractAddress == contractAddress && - token.networkId == networkId && - token.derivationPath == currency.network.derivationPath.value - } != null - } - - val newCoins = createCoinsForNewTokens( - userWalletId = userWalletId, - newTokens = filteredCurrencies.filterIsInstance(), - savedCurrencies = savedCurrencies.tokens, + val currenciesToAdd = populateCurrenciesWithMissedCoins( + currencies = filterAlreadyAddedCurrencies(savedCurrencies.tokens, currencies), ) - val newCurrencies = (newCoins + filteredCurrencies).distinct() - val updatedResponse = savedCurrencies.copy( - tokens = savedCurrencies.tokens + newCurrencies.map(userTokensResponseFactory::createResponseToken), + tokens = savedCurrencies.tokens + currenciesToAdd.map(userTokensResponseFactory::createResponseToken), ) storeAndPushTokens( userWalletId = userWalletId, @@ -133,34 +118,47 @@ internal class DefaultCurrenciesRepository( } } - private suspend fun createCoinsForNewTokenList( - userWalletId: UserWalletId, - newTokens: List, - ): List { - return newTokens.mapNotNull { - cryptoCurrencyFactory.createCoin( - blockchain = getBlockchain(networkId = it.network.id), - extraDerivationPath = it.network.derivationPath.value, - scanResponse = getUserWallet(userWalletId).scanResponse, - ) - }.distinct() + private fun filterAlreadyAddedCurrencies( + savedCurrencies: List, + currenciesToAdd: List, + ): List { + return currenciesToAdd.filter { currency -> + val blockchain = getBlockchain(networkId = currency.network.id) + val networkId = blockchain.toNetworkId() + val contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress + + savedCurrencies.none { token -> + token.contractAddress == contractAddress && + token.networkId == networkId && + token.derivationPath == currency.network.derivationPath.value + } + } } - private suspend fun createCoinsForNewTokens( - userWalletId: UserWalletId, - newTokens: List, - savedCurrencies: List, - ): List { - return newTokens - .filterNot { savedCurrencies.hasCoinForToken(it.network) } // tokens without coins - .mapNotNull { - cryptoCurrencyFactory.createCoin( - blockchain = getBlockchain(networkId = it.network.id), - extraDerivationPath = it.network.derivationPath.value, - scanResponse = getUserWallet(userWalletId).scanResponse, - ) + private fun populateCurrenciesWithMissedCoins(currencies: List): List { + val networkToCoin = mutableMapOf() + val networkToTokens = mutableMapOf>() + + currencies.forEach { currency -> + when (currency) { + is CryptoCurrency.Coin -> { + networkToCoin[currency.network] = currency + } + is CryptoCurrency.Token -> { + val tokens = networkToTokens.getOrElse(currency.network, ::emptyList) + networkToTokens[currency.network] = tokens + currency + } } - .distinct() + } + + return buildList { + networkToTokens.forEach { (network, networkTokens) -> + val networkCoin = networkToCoin[network] ?: cryptoCurrencyFactory.createCoin(network) + + add(networkCoin) + addAll(networkTokens) + } + } } override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) = diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt index cb42f40234..dd2f977457 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt @@ -24,32 +24,32 @@ class SaveManagedTokensUseCase( userWalletId: UserWalletId, currenciesToAdd: Map>, currenciesToRemove: Map>, - ): Either { - return Either.catch { - val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId) - val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId) - derivationsRepository.derivePublicKeysByNetworks( - userWalletId = userWalletId, - networks = currenciesToAdd.values.flatten(), - ) - val newCurrenciesList = currenciesRepository - .getMultiCurrencyWalletCurrenciesSync(userWalletId) - .filterNot(removingCurrencies::contains) - .toMutableList() - .also { it.addAll(addingCurrencies) } - currenciesRepository.saveNewCurrenciesList(userWalletId, newCurrenciesList) + ): Either = Either.catch { + val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId) + val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId) - val existingCurrencies = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId) - removeCurrenciesFromWalletManager( - userWalletId = userWalletId, - currencies = removingCurrencies.filterNot(existingCurrencies::contains), - ) - refreshUpdatedNetworks( - userWalletId = userWalletId, - existingCurrencies = existingCurrencies, - currenciesToAdd = addingCurrencies, - ) - } + derivationsRepository.derivePublicKeysByNetworks( + userWalletId = userWalletId, + networks = currenciesToAdd.values.flatten(), + ) + val newCurrenciesList = currenciesRepository + .getMultiCurrencyWalletCurrenciesSync(userWalletId) + .filterNot(removingCurrencies::contains) + .toMutableList() + .also { it.addAll(addingCurrencies) } + + currenciesRepository.saveNewCurrenciesList(userWalletId, newCurrenciesList) + + val existingCurrencies = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId) + removeCurrenciesFromWalletManager( + userWalletId = userWalletId, + currencies = removingCurrencies.filterNot(existingCurrencies::contains), + ) + refreshUpdatedNetworks( + userWalletId = userWalletId, + existingCurrencies = existingCurrencies, + currenciesToAdd = addingCurrencies, + ) } private suspend fun removeCurrenciesFromWalletManager(