Updated on 2026-08-14
This commit is contained in:
parent
6f47e7d742
commit
6a5a8300cf
10 changed files with 116 additions and 18 deletions
|
|
@ -1,11 +1,13 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -64,6 +66,18 @@ object MarketsDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFilterNetworksUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): FilterAvailableNetworksForWalletUseCase {
|
||||
return FilterAvailableNetworksForWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetTokenExchangesUseCase(marketsTokenRepository: MarketsTokenRepository): GetTokenExchangesUseCase {
|
||||
|
|
|
|||
|
|
@ -64,4 +64,12 @@ inline fun <T> MutableList<T>.addOrReplace(item: T, predicate: (T) -> Boolean) {
|
|||
if (!isReplaced) {
|
||||
add(item)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> List<T>.filterIf(condition: Boolean, predicate: (T) -> Boolean): List<T> {
|
||||
return if (condition) {
|
||||
this.filter(predicate)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ import com.tangem.datasource.local.preferences.utils.getObject
|
|||
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
|
||||
import com.tangem.datasource.local.preferences.utils.storeObject
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.common.extensions.canHandleBlockchain
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -33,6 +35,7 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.filterIf
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
|
|
@ -47,7 +50,7 @@ internal class DefaultCurrenciesRepository(
|
|||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val expressServiceLoader: ExpressServiceLoader,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) : CurrenciesRepository {
|
||||
|
||||
private val demoConfig = DemoConfig()
|
||||
|
|
@ -486,12 +489,14 @@ internal class DefaultCurrenciesRepository(
|
|||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun getAllWalletsCryptoCurrencies(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
needFilterByAvailable: Boolean,
|
||||
): Flow<Map<UserWallet, List<CryptoCurrency>>> {
|
||||
return userWalletsStore.userWallets.flatMapLatest { userWallets ->
|
||||
userWallets.forEach { fetchTokensIfCacheExpired(userWallet = it, refresh = false) }
|
||||
|
||||
val userWalletsWithCurrencies = userWallets
|
||||
.filterNot(UserWallet::isLocked)
|
||||
.filterIf(needFilterByAvailable) { it.filterWalletByAvailableBlockchain(currencyRawId) }
|
||||
.map { userWallet ->
|
||||
if (userWallet.isMultiCurrency) {
|
||||
getSavedUserTokensResponse(userWallet.walletId).map { storedTokens ->
|
||||
|
|
@ -525,6 +530,15 @@ internal class DefaultCurrenciesRepository(
|
|||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.filterWalletByAvailableBlockchain(currencyRawId: CryptoCurrency.RawID): Boolean {
|
||||
val blockchain = Blockchain.fromNetworkId(currencyRawId.value) ?: return true
|
||||
return this.scanResponse.card.canHandleBlockchain(
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = this.cardTypesResolver,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
|
||||
override fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean {
|
||||
val blockchain = Blockchain.fromNetworkId(network.backendId)
|
||||
return blockchain?.isNetworkFeeZero() ?: false
|
||||
|
|
|
|||
|
|
@ -17,12 +17,21 @@ dependencies {
|
|||
api(projects.domain.core)
|
||||
api(projects.domain.markets.models)
|
||||
api(projects.domain.wallets.models)
|
||||
api(projects.domain.models)
|
||||
api(projects.domain.legacy)
|
||||
api(projects.domain.wallets)
|
||||
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.tokens)
|
||||
|
||||
api(projects.core.pagination)
|
||||
|
||||
/* Libs */
|
||||
api(projects.libs.blockchainSdk)
|
||||
|
||||
/* SDK */
|
||||
implementation(tangemDeps.blockchain)
|
||||
|
||||
/* Utils */
|
||||
implementation(deps.kotlin.serialization)
|
||||
implementation(projects.core.utils)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.domain.markets
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.domain.common.extensions.supportedBlockchains
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
class FilterAvailableNetworksForWalletUseCase(
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Filters [networks] list according supported blockchains for this card
|
||||
* If [userWalletId] not found then returns the same list
|
||||
*/
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<TokenMarketInfo.Network>,
|
||||
): Set<TokenMarketInfo.Network> {
|
||||
val userWallet = userWalletsListManager.userWalletsSync.firstOrNull {
|
||||
it.walletId == userWalletId
|
||||
} ?: return networks.toSet()
|
||||
|
||||
val supportedBlockchains = userWallet.scanResponse.card.supportedBlockchains(
|
||||
cardTypesResolver = userWallet.scanResponse.cardTypesResolver,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
||||
return networks.filter {
|
||||
val blockchain = Blockchain.fromNetworkId(it.networkId)
|
||||
supportedBlockchains.contains(blockchain)
|
||||
}.toSet()
|
||||
}
|
||||
}
|
||||
|
|
@ -42,8 +42,9 @@ class GetAllWalletsCryptoCurrencyStatusesUseCase(
|
|||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
operator fun invoke(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
needFilterByAvailable: Boolean = false,
|
||||
): Flow<Map<UserWallet, List<Either<CurrencyStatusError, CryptoCurrencyStatus>>>> {
|
||||
return currenciesRepository.getAllWalletsCryptoCurrencies(currencyRawId)
|
||||
return currenciesRepository.getAllWalletsCryptoCurrencies(currencyRawId, needFilterByAvailable)
|
||||
.flatMapLatest { userWalletsWithCurrencies: Map<UserWallet, List<CryptoCurrency>> ->
|
||||
val walletStatusFlows = userWalletsWithCurrencies.map { (userWallet, cryptoCurrencies) ->
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
|
|
@ -64,6 +65,7 @@ class GetAllWalletsCryptoCurrencyStatusesUseCase(
|
|||
}
|
||||
|
||||
combine(walletStatusFlows) { it.toMap() }
|
||||
.onEmpty { emit(emptyMap()) }
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,10 @@ interface CurrenciesRepository {
|
|||
): CryptoCurrency.Token
|
||||
|
||||
/** Get crypto currencies by [currencyRawId] from all user wallets */
|
||||
fun getAllWalletsCryptoCurrencies(currencyRawId: CryptoCurrency.RawID): Flow<Map<UserWallet, List<CryptoCurrency>>>
|
||||
fun getAllWalletsCryptoCurrencies(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
needFilterByAvailable: Boolean,
|
||||
): Flow<Map<UserWallet, List<CryptoCurrency>>>
|
||||
|
||||
fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean
|
||||
}
|
||||
|
|
@ -155,6 +155,7 @@ internal class MockCurrenciesRepository(
|
|||
|
||||
override fun getAllWalletsCryptoCurrencies(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
needFilterByAvailable: Boolean,
|
||||
): Flow<Map<UserWallet, List<CryptoCurrency>>> {
|
||||
return emptyFlow()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ internal class PortfolioDataLoader @Inject constructor(
|
|||
private fun getAllWalletsCryptoCurrenciesData(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
): Flow<Map<UserWallet, List<PortfolioData.CryptoCurrencyData>>> {
|
||||
return getAllWalletsCryptoCurrencyStatusesUseCase(currencyRawId)
|
||||
return getAllWalletsCryptoCurrencyStatusesUseCase(currencyRawId, true)
|
||||
.distinctUntilChanged()
|
||||
.map { walletsWithMaybeStatuses ->
|
||||
walletsWithMaybeStatuses.mapValues { entry ->
|
||||
|
|
@ -94,20 +94,21 @@ internal class PortfolioDataLoader @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
}.onEmpty {
|
||||
emit(
|
||||
walletsWithStatuses.mapValues { (wallet, statuses) ->
|
||||
statuses.map {
|
||||
PortfolioData.CryptoCurrencyData(
|
||||
userWallet = wallet,
|
||||
status = it,
|
||||
actions = emptyList(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
.onEmpty {
|
||||
emit(
|
||||
walletsWithStatuses.mapValues { (wallet, statuses) ->
|
||||
statuses.map {
|
||||
PortfolioData.CryptoCurrencyData(
|
||||
userWallet = wallet,
|
||||
status = it,
|
||||
actions = emptyList(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}.onEmpty {
|
||||
emit(emptyMap())
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.card.HasMissedDerivationsUseCase
|
||||
import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase
|
||||
import com.tangem.domain.managetokens.model.CurrencyUnsupportedState
|
||||
import com.tangem.domain.markets.FilterAvailableNetworksForWalletUseCase
|
||||
import com.tangem.domain.markets.SaveMarketTokensUseCase
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -49,6 +50,7 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
private val portfolioDataLoader: PortfolioDataLoader,
|
||||
private val hasMissedDerivationsUseCase: HasMissedDerivationsUseCase,
|
||||
private val saveMarketTokensUseCase: SaveMarketTokensUseCase,
|
||||
private val filterAvailableNetworks: FilterAvailableNetworksForWalletUseCase,
|
||||
private val addToPortfolioManager: AddToPortfolioManager,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model() {
|
||||
|
|
@ -175,10 +177,16 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
flow2 = selectedMultiWalletIdFlow,
|
||||
flow3 = addToPortfolioManager.getAddToPortfolioData(),
|
||||
transform = { portfolioBSVisibilityModel, selectedWalletId, addToPortfolioData ->
|
||||
val filteredNetworks = selectedWalletId?.let {
|
||||
filterAvailableNetworks(selectedWalletId, addToPortfolioData.availableNetworks ?: emptySet())
|
||||
} ?: emptySet()
|
||||
|
||||
PortfolioUIData(
|
||||
portfolioBSVisibilityModel = portfolioBSVisibilityModel,
|
||||
selectedWalletId = selectedWalletId,
|
||||
addToPortfolioData = addToPortfolioData,
|
||||
addToPortfolioData = addToPortfolioData.copy(
|
||||
availableNetworks = filteredNetworks,
|
||||
),
|
||||
hasMissedDerivations = hasMissedDerivations(selectedWalletId, addToPortfolioData),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue