Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-04 14:24:34 +05:00
parent f55f6f8461
commit 0fdcdda8d5
15 changed files with 213 additions and 250 deletions

View file

@ -4,6 +4,9 @@ import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.*
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -57,11 +60,17 @@ internal object ManageTokensDomainModule {
@Provides
@Singleton
fun provideSaveManagedTokensUseCase(
manageTokensRepository: ManageTokensRepository,
customTokensRepository: CustomTokensRepository,
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
networksRepository: NetworksRepository,
derivationsRepository: DerivationsRepository,
): SaveManagedTokensUseCase {
return SaveManagedTokensUseCase(
manageTokensRepository = manageTokensRepository,
customTokensRepository = customTokensRepository,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
derivationsRepository = derivationsRepository,
)
}
@ -81,4 +90,10 @@ internal object ManageTokensDomainModule {
): ValidateDerivationPathUseCase {
return ValidateDerivationPathUseCase(customTokensRepository)
}
@Provides
@Singleton
fun provideCheckHasLinkedTokensUseCase(repository: ManageTokensRepository): CheckHasLinkedTokensUseCase {
return CheckHasLinkedTokensUseCase(repository)
}
}

View file

@ -431,12 +431,6 @@ internal object TokensDomainModule {
)
}
@Provides
@Singleton
fun provideCheckHasLinkedTokensUseCase(currenciesRepository: CurrenciesRepository): CheckHasLinkedTokensUseCase {
return CheckHasLinkedTokensUseCase(currenciesRepository)
}
@Provides
@Singleton
fun provideGetCurrencyCheckUseCase(currencyChecksRepository: CurrencyChecksRepository): GetCurrencyCheckUseCase {

View file

@ -130,6 +130,21 @@ internal class DefaultCustomTokensRepository(
return cryptoCurrencyFactory.createCoin(network)
}
override fun createToken(
managedCryptoCurrency: ManagedCryptoCurrency.Token,
sourceNetwork: ManagedCryptoCurrency.SourceNetwork.Default,
rawId: String?,
): CryptoCurrency.Token {
return cryptoCurrencyFactory.createToken(
network = sourceNetwork.network,
rawId = rawId,
name = managedCryptoCurrency.name,
symbol = managedCryptoCurrency.symbol,
decimals = sourceNetwork.decimals,
contractAddress = sourceNetwork.contractAddress,
)
}
override suspend fun createCustomToken(
networkId: Network.ID,
derivationPath: Network.DerivationPath,

View file

@ -3,27 +3,16 @@ package com.tangem.data.managetokens
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.isSupportedInApp
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.data.common.api.safeApiCall
import com.tangem.data.common.currency.CryptoCurrencyFactory
import com.tangem.data.common.currency.UserTokensResponseFactory
import com.tangem.data.common.currency.getBlockchain
import com.tangem.data.common.currency.hasCoinForToken
import com.tangem.data.common.utils.retryOnError
import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
import com.tangem.data.managetokens.utils.ManagedCryptoCurrencyFactory
import com.tangem.data.tokens.utils.UserTokensBackwardCompatibility
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.express.models.TangemExpressValues
import com.tangem.datasource.api.express.models.request.AssetsRequestBody
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.storeObject
import com.tangem.datasource.local.token.ExpressAssetsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.common.extensions.supportedBlockchains
import com.tangem.domain.common.util.cardTypesResolver
@ -35,8 +24,6 @@ import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.walletmanager.model.TokenInfo
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.pagination.BatchFetchResult
@ -44,8 +31,6 @@ import com.tangem.pagination.BatchListSource
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
import com.tangem.pagination.toBatchFlow
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import timber.log.Timber
@Suppress("LongParameterList")
internal class DefaultManageTokensRepository(
@ -54,15 +39,9 @@ internal class DefaultManageTokensRepository(
private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
private val walletManagerFacade: WalletManagersFacade,
private val tangemExpressApi: TangemExpressApi,
private val expressAssetsStore: ExpressAssetsStore,
) : ManageTokensRepository {
private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory()
private val cryptoCurrencyFactory = CryptoCurrencyFactory()
private val userTokensResponseFactory = UserTokensResponseFactory()
private val userTokensBackwardCompatibility = UserTokensBackwardCompatibility()
// region getTokenListBatchFlow
override fun getTokenListBatchFlow(
@ -108,7 +87,7 @@ internal class DefaultManageTokensRepository(
retryOnError(call = call)
}
val tokensResponse = getStoredUserTokens(request.params.userWalletId)
val tokensResponse = request.params.userWalletId?.let { getSavedUserTokensResponseSync(it) }
val items = if (isFirstBatchFetching &&
tokensResponse != null &&
userWallet != null &&
@ -135,16 +114,6 @@ internal class DefaultManageTokensRepository(
},
)
private suspend fun getStoredUserTokens(userWalletId: UserWalletId?): UserTokensResponse? {
return if (userWalletId != null) {
appPreferencesStore.getObjectSyncOrNull(
key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue),
)
} else {
null
}
}
private suspend fun getUserWallet(userWalletId: UserWalletId): UserWallet {
return requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
"Unable to find a user wallet with provided ID: $userWalletId"
@ -160,158 +129,44 @@ internal class DefaultManageTokensRepository(
}
// endregion
// region addManagedCurrencies
override suspend fun saveManagedCurrencies(
override suspend fun hasLinkedTokens(
userWalletId: UserWalletId,
currenciesToAdd: Map<ManagedCryptoCurrency.Token, Set<Network>>,
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
) {
return withContext(dispatchers.io) {
val savedCurrencies = requireNotNull(
value = getSavedUserTokensResponseSync(key = userWalletId),
lazyMessage = { "Saved tokens empty. Can not perform add currencies action" },
)
network: Network,
tempAddedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
tempRemovedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
): Boolean {
val addedTokens = tempAddedTokens.mapToResponseTokens()
val removedTokens = tempRemovedTokens.mapToResponseTokens()
val filteredTokens = currenciesToAdd.mapToTokenDataList()
.filterNot { tokenData ->
val blockchain = getBlockchain(networkId = tokenData.sourceNetwork.network.id)
val networkId = blockchain.toNetworkId()
val contractAddress = (tokenData.sourceNetwork as? SourceNetwork.Default)?.contractAddress
savedCurrencies.tokens.firstOrNull { token ->
token.contractAddress == contractAddress &&
token.networkId == networkId &&
token.derivationPath == tokenData.sourceNetwork.network.derivationPath.value
} != null
}
val newCoins = createCoinsForNewTokens(
userWalletId = userWalletId,
newTokensNetworks = filteredTokens.mapNotNull { tokenData ->
(tokenData.sourceNetwork as? SourceNetwork.Default)?.network
},
savedCurrencies = savedCurrencies.tokens,
)
val tokensToSave = filteredTokens.mapToUserResponseToken()
val tokensToRemove = currenciesToRemove.mapToTokenDataList()
removeCurrenciesFromWalletManager(userWalletId = userWalletId, tokensDataList = tokensToRemove)
val newCurrencies = (newCoins + tokensToSave).distinct()
val updatedResponse = savedCurrencies.copy(
tokens = savedCurrencies.tokens + newCurrencies - tokensToRemove.mapToUserResponseToken().toSet(),
)
storeAndPushTokens(userWalletId = userWalletId, response = updatedResponse)
fetchExchangeableUserMarketCoinsByIds(userWalletId = userWalletId, userTokens = updatedResponse)
}
}
private suspend fun storeAndPushTokens(userWalletId: UserWalletId, response: UserTokensResponse) {
val compatibleUserTokensResponse = userTokensBackwardCompatibility.applyCompatibilityAndGetUpdated(response)
appPreferencesStore.storeObject(
key = PreferencesKeys.getUserTokensKey(userWalletId = userWalletId.stringValue),
value = compatibleUserTokensResponse,
val storedTokens = requireNotNull(
value = getSavedUserTokensResponseSync(userWalletId),
lazyMessage = { "Unable to find tokens response for user wallet with provided ID: $userWalletId" },
)
val newTokensList = storedTokens.tokens + addedTokens - removedTokens.toSet()
pushTokens(userWalletId, response)
}
private suspend fun pushTokens(userWalletId: UserWalletId, response: UserTokensResponse) {
safeApiCall({ tangemTechApi.saveUserTokens(userWalletId.stringValue, response).bind() }) {
Timber.e(it, "Unable to save user tokens for: ${userWalletId.stringValue}")
return newTokensList.any {
it.contractAddress != null &&
it.networkId == network.backendId &&
it.derivationPath == network.derivationPath.value
}
}
private suspend fun fetchExchangeableUserMarketCoinsByIds(
userWalletId: UserWalletId,
userTokens: UserTokensResponse,
) {
try {
val tokensList = userTokens.tokens
.map {
LeastTokenInfo(
contractAddress = it.contractAddress ?: TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE,
network = it.networkId,
)
}
if (tokensList.isNotEmpty()) {
val response = tangemExpressApi.getAssets(
AssetsRequestBody(
tokensList = tokensList,
),
)
expressAssetsStore.store(userWalletId, response.getOrThrow())
}
} catch (e: Throwable) {
Timber.e(e, "Unable to fetch assets for: ${userWalletId.stringValue}")
}
}
private suspend fun removeCurrenciesFromWalletManager(
userWalletId: UserWalletId,
tokensDataList: List<TokenWithSourceNetwork>,
) {
walletManagerFacade.removeTokensByTokenInfo(
userWalletId = userWalletId,
tokenInfos = tokensDataList.mapNotNullTo(hashSetOf()) { tokenData ->
val contractAddress =
(tokenData.sourceNetwork as? SourceNetwork.Default)?.contractAddress ?: return@mapNotNullTo null
TokenInfo(
network = tokenData.sourceNetwork.network,
name = tokenData.token.name,
symbol = tokenData.token.symbol,
contractAddress = contractAddress,
decimals = tokenData.sourceNetwork.decimals,
id = tokenData.token.id.value,
)
},
)
walletManagerFacade.remove(
userWalletId = userWalletId,
networks = tokensDataList.mapNotNullTo(hashSetOf()) { tokenData ->
(tokenData.sourceNetwork as? SourceNetwork.Main)?.network
},
)
}
private suspend fun createCoinsForNewTokens(
userWalletId: UserWalletId,
newTokensNetworks: List<Network>,
savedCurrencies: List<UserTokensResponse.Token>,
): List<UserTokensResponse.Token> {
return newTokensNetworks
.filterNot { savedCurrencies.hasCoinForToken(it) } // tokens without coins
.mapNotNull {
cryptoCurrencyFactory.createCoin(
blockchain = getBlockchain(networkId = it.id),
extraDerivationPath = it.derivationPath.value,
derivationStyleProvider = getUserWallet(userWalletId).scanResponse.derivationStyleProvider,
)
}
.distinct()
.map(userTokensResponseFactory::createResponseToken)
}
private fun List<TokenWithSourceNetwork>.mapToUserResponseToken(): List<UserTokensResponse.Token> {
return map { tokenData ->
val blockchain = getBlockchain(tokenData.sourceNetwork.network.id)
UserTokensResponse.Token(
id = tokenData.token.id.value,
networkId = blockchain.toNetworkId(),
derivationPath = tokenData.sourceNetwork.network.derivationPath.value,
name = tokenData.token.name,
symbol = tokenData.token.symbol,
decimals = tokenData.sourceNetwork.decimals,
contractAddress = (tokenData.sourceNetwork as? SourceNetwork.Default)?.contractAddress,
)
}
}
private fun Map<ManagedCryptoCurrency.Token, Set<Network>>.mapToTokenDataList(): List<TokenWithSourceNetwork> {
private fun Map<ManagedCryptoCurrency.Token, Set<Network>>.mapToResponseTokens(): List<UserTokensResponse.Token> {
return flatMap { (token, networks) ->
token.availableNetworks
.filter { sourceNetwork -> networks.contains(sourceNetwork.network) }
.map { sourceNetwork -> TokenWithSourceNetwork(token = token, sourceNetwork = sourceNetwork) }
.map { sourceNetwork ->
val blockchain = getBlockchain(sourceNetwork.network.id)
UserTokensResponse.Token(
id = token.id.value,
networkId = blockchain.toNetworkId(),
derivationPath = sourceNetwork.network.derivationPath.value,
name = token.name,
symbol = token.symbol,
decimals = sourceNetwork.decimals,
contractAddress = (sourceNetwork as? SourceNetwork.Default)?.contractAddress,
)
}
}
}

View file

@ -3,10 +3,8 @@ package com.tangem.data.managetokens.di
import com.tangem.data.managetokens.DefaultCustomTokensRepository
import com.tangem.data.managetokens.DefaultManageTokensRepository
import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.ExpressAssetsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.managetokens.repository.ManageTokensRepository
@ -30,9 +28,6 @@ internal object ManageTokensDataModule {
manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
walletManagersFacade: WalletManagersFacade,
tangemExpressApi: TangemExpressApi,
expressAssetsStore: ExpressAssetsStore,
): ManageTokensRepository {
return DefaultManageTokensRepository(
tangemTechApi,
@ -40,9 +35,6 @@ internal object ManageTokensDataModule {
manageTokensUpdateFetcher,
appPreferencesStore,
dispatchers,
walletManagersFacade,
tangemExpressApi,
expressAssetsStore,
)
}

View file

@ -478,26 +478,6 @@ internal class DefaultCurrenciesRepository(
) ?: error("Unable to create token")
}
override suspend fun hasTokens(userWalletId: UserWalletId, network: Network): Boolean {
val userWallet = getUserWallet(userWalletId)
fetchTokensIfCacheExpired(userWallet, refresh = false)
val storedTokens = requireNotNull(
value = appPreferencesStore.getObjectSyncOrNull<UserTokensResponse>(
key = PreferencesKeys.getUserTokensKey(userWallet.walletId.stringValue),
),
lazyMessage = {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
},
)
return storedTokens.tokens.any {
it.contractAddress != null &&
it.networkId == network.backendId &&
it.derivationPath == network.derivationPath.value
}
}
@OptIn(ExperimentalCoroutinesApi::class)
override fun getAllWalletsCryptoCurrencies(currencyRawId: String): Flow<Map<UserWallet, List<CryptoCurrency>>> {
return userWalletsStore.userWallets.flatMapLatest { userWallets ->

View file

@ -15,6 +15,7 @@ dependencies {
api(projects.domain.core)
implementation(projects.domain.wallets.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.tokens)
implementation(projects.domain.card)
implementation(projects.domain.legacy)

View file

@ -0,0 +1,28 @@
package com.tangem.domain.managetokens
import arrow.core.Either
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
class CheckHasLinkedTokensUseCase(
private val repository: ManageTokensRepository,
) {
suspend operator fun invoke(
userWalletId: UserWalletId,
network: Network,
tempAddedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
tempRemovedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
): Either<Throwable, Boolean> {
return Either.catch {
repository.hasLinkedTokens(
userWalletId = userWalletId,
network = network,
tempAddedTokens = tempAddedTokens,
tempRemovedTokens = tempRemovedTokens,
)
}
}
}

View file

@ -4,12 +4,19 @@ import arrow.core.Either
import arrow.core.flatten
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
class SaveManagedTokensUseCase(
private val manageTokensRepository: ManageTokensRepository,
private val customTokensRepository: CustomTokensRepository,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val networksRepository: NetworksRepository,
private val derivationsRepository: DerivationsRepository,
) {
@ -19,15 +26,102 @@ class SaveManagedTokensUseCase(
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
): Either<Throwable, Unit> {
return Either.catch {
derivationsRepository.derivePublicKeysByNetworks(
userWalletId = userWalletId,
networks = currenciesToAdd.values.flatten(),
)
manageTokensRepository.saveManagedCurrencies(
userWalletId = userWalletId,
currenciesToAdd = currenciesToAdd,
currenciesToRemove = currenciesToRemove,
)
// TODO: Currently order is matter. [REDACTED_JIRA]
removeCurrencies(userWalletId, currenciesToRemove)
addCurrencies(userWalletId, currenciesToAdd)
}
}
private suspend fun removeCurrencies(
userWalletId: UserWalletId,
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
) {
if (currenciesToRemove.isEmpty()) return
val currencies = currenciesToRemove.mapToCryptoCurrencies()
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(),
)
}
private suspend fun addCurrencies(
userWalletId: UserWalletId,
currenciesToAdd: Map<ManagedCryptoCurrency.Token, Set<Network>>,
) {
if (currenciesToAdd.isEmpty()) return
val existingCurrencies = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
val currencies = currenciesToAdd.mapToCryptoCurrencies()
derivationsRepository.derivePublicKeysByNetworks(
userWalletId = userWalletId,
networks = currenciesToAdd.values.flatten(),
)
currenciesRepository.addCurrencies(userWalletId, currencies)
refreshUpdatedNetworks(
userWalletId = userWalletId,
existingCurrencies = existingCurrencies,
currenciesToAdd = currencies,
)
}
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())
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
}
/**
* 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 fun Map<ManagedCryptoCurrency.Token, Set<Network>>.mapToCryptoCurrencies(): List<CryptoCurrency> {
return flatMap { (token, networks) ->
token.availableNetworks
.filter { sourceNetwork -> networks.contains(sourceNetwork.network) }
.map { sourceNetwork ->
when (sourceNetwork) {
is ManagedCryptoCurrency.SourceNetwork.Default -> customTokensRepository.createToken(
managedCryptoCurrency = token,
sourceNetwork = sourceNetwork,
rawId = token.id.value,
)
is ManagedCryptoCurrency.SourceNetwork.Main -> customTokensRepository.createCoin(
networkId = sourceNetwork.id,
derivationPath = sourceNetwork.network.derivationPath,
)
}
}
}
}
}

View file

@ -26,6 +26,12 @@ interface CustomTokensRepository {
fun createCoin(networkId: Network.ID, derivationPath: Network.DerivationPath): CryptoCurrency.Coin
fun createToken(
managedCryptoCurrency: ManagedCryptoCurrency.Token,
sourceNetwork: ManagedCryptoCurrency.SourceNetwork.Default,
rawId: String?,
): CryptoCurrency.Token
suspend fun createCustomToken(
networkId: Network.ID,
derivationPath: Network.DerivationPath,

View file

@ -10,9 +10,10 @@ interface ManageTokensRepository {
fun getTokenListBatchFlow(context: ManageTokensListBatchingContext, batchSize: Int): ManageTokensListBatchFlow
suspend fun saveManagedCurrencies(
suspend fun hasLinkedTokens(
userWalletId: UserWalletId,
currenciesToAdd: Map<ManagedCryptoCurrency.Token, Set<Network>>,
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
)
network: Network,
tempAddedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
tempRemovedTokens: Map<ManagedCryptoCurrency.Token, Set<Network>>,
): Boolean
}

View file

@ -1,17 +0,0 @@
package com.tangem.domain.tokens
import arrow.core.Either
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId
class CheckHasLinkedTokensUseCase(
private val currenciesRepository: CurrenciesRepository,
) {
suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either<Throwable, Boolean> {
return Either.catch {
currenciesRepository.hasTokens(userWalletId, network)
}
}
}

View file

@ -234,8 +234,6 @@ interface CurrenciesRepository {
networkId: String,
): CryptoCurrency.Token
suspend fun hasTokens(userWalletId: UserWalletId, network: Network): Boolean
/** Get crypto currencies by [currencyRawId] from all user wallets */
fun getAllWalletsCryptoCurrencies(currencyRawId: String): Flow<Map<UserWallet, List<CryptoCurrency>>>
}

View file

@ -150,10 +150,6 @@ internal class MockCurrenciesRepository(
error("not implemented")
}
override suspend fun hasTokens(userWalletId: UserWalletId, network: Network): Boolean {
return false
}
override fun getAllWalletsCryptoCurrencies(currencyRawId: String): Flow<Map<UserWallet, List<CryptoCurrency>>> {
return emptyFlow()
}

View file

@ -12,7 +12,7 @@ import com.tangem.domain.managetokens.model.ManageTokensListBatchingContext
import com.tangem.domain.managetokens.model.ManageTokensListConfig
import com.tangem.domain.managetokens.model.ManageTokensUpdateAction
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.tokens.CheckHasLinkedTokensUseCase
import com.tangem.domain.managetokens.CheckHasLinkedTokensUseCase
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
@ -198,7 +198,12 @@ internal class ManageTokensListManager @Inject constructor(
}
override suspend fun checkHasLinkedTokens(userWalletId: UserWalletId, network: Network): Boolean {
return checkHasLinkedTokensUseCase(userWalletId, network).getOrElse {
return checkHasLinkedTokensUseCase(
userWalletId = userWalletId,
network = network,
tempAddedTokens = changedCurrenciesManager.currenciesToAdd.value,
tempRemovedTokens = changedCurrenciesManager.currenciesToRemove.value,
).getOrElse {
Timber.e(
it,
"""