Updated on 2026-08-14
This commit is contained in:
parent
b27e8171fb
commit
4ea8243da3
19 changed files with 375 additions and 126 deletions
|
|
@ -36,6 +36,7 @@ internal class CryptoPortfolioConverter @AssistedInject constructor(
|
|||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = tokens,
|
||||
userWallet = userWallet,
|
||||
accountIndex = value.derivationIndex.toDerivationIndex(),
|
||||
).toSet()
|
||||
} else {
|
||||
emptySet()
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import arrow.core.Option
|
|||
import arrow.core.some
|
||||
import com.tangem.data.account.store.AccountsResponseStoreFactory
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
|
|
@ -48,10 +48,13 @@ internal class AccountListCryptoCurrenciesProducer @AssistedInject constructor(
|
|||
.map { response ->
|
||||
if (response == null) return@map emptySet()
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = response.toUserTokensResponse(),
|
||||
userWallet = userWallet,
|
||||
).toSet()
|
||||
response.accounts.flatMapTo(hashSetOf()) { accountDTO ->
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = accountDTO.tokens.orEmpty(),
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex(accountDTO.derivationIndex).getOrNull(),
|
||||
)
|
||||
}
|
||||
}
|
||||
.onEmpty { emit(emptySet()) }
|
||||
.distinctUntilChanged()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.blockchainsdk.utils.fromNetworkId
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.blockchainsdk.utils.toCoinId
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -18,7 +19,7 @@ class CryptoCurrencyFactory(
|
|||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) {
|
||||
|
||||
private val networkFactory by lazy(LazyThreadSafetyMode.NONE) { NetworkFactory(excludedBlockchains) }
|
||||
val networkFactory by lazy(LazyThreadSafetyMode.NONE) { NetworkFactory(excludedBlockchains) }
|
||||
|
||||
@Suppress("LongParameterList") // Yep, it's long
|
||||
fun createToken(
|
||||
|
|
@ -89,6 +90,7 @@ class CryptoCurrencyFactory(
|
|||
blockchain: Blockchain,
|
||||
extraDerivationPath: String?,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): CryptoCurrency.Coin? {
|
||||
if (blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to map the SDK token to the domain token with Unknown blockchain")
|
||||
|
|
@ -99,6 +101,7 @@ class CryptoCurrencyFactory(
|
|||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
return createCoin(network)
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ import com.tangem.blockchainsdk.utils.toBlockchain
|
|||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.data.common.tokens.getDefaultWalletBlockchains
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -140,15 +139,32 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
userWallet: UserWallet,
|
||||
networks: Set<Network>,
|
||||
): Map<Network, List<CryptoCurrency>> {
|
||||
val response = getUserTokensResponse(userWalletId = userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
val existingNetworkWithCurrencies = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val response = walletAccountsFetcher.getSaved(userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
|
||||
val existingNetworkWithCurrencies = responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token ->
|
||||
networks.any { it.backendId == token.networkId && it.derivationPath.value == token.derivationPath }
|
||||
},
|
||||
userWallet = userWallet,
|
||||
)
|
||||
response.accounts.flatMapTo(hashSetOf()) { accountDTO ->
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = accountDTO.tokens.orEmpty().filter { token ->
|
||||
networks.any {
|
||||
it.backendId == token.networkId && it.derivationPath.value == token.derivationPath
|
||||
}
|
||||
},
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex(accountDTO.derivationIndex).getOrNull(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val response = userTokensResponseStore.getSyncOrNull(userWalletId = userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token ->
|
||||
networks.any { it.backendId == token.networkId && it.derivationPath.value == token.derivationPath }
|
||||
},
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
.groupBy(CryptoCurrency::network)
|
||||
|
||||
return networks.associateWith { emptyList<CryptoCurrency>() } + existingNetworkWithCurrencies
|
||||
|
|
@ -158,24 +174,29 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
userWallet: UserWallet,
|
||||
rawIds: Set<Network.RawID>,
|
||||
): Map<Network.RawID, List<CryptoCurrency>> {
|
||||
val response = getUserTokensResponse(userWalletId = userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
|
||||
val networkIds = rawIds.map { it.toBlockchain().toNetworkId() }
|
||||
|
||||
return responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token -> token.networkId in networkIds },
|
||||
userWallet = userWallet,
|
||||
)
|
||||
.groupBy { it.network.id.rawId }
|
||||
}
|
||||
|
||||
private suspend fun getUserTokensResponse(userWalletId: UserWalletId): UserTokensResponse? {
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
walletAccountsFetcher.getSaved(userWalletId)?.toUserTokensResponse()
|
||||
val response = walletAccountsFetcher.getSaved(userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
|
||||
response.accounts.flatMapTo(hashSetOf()) { accountDTO ->
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = accountDTO.tokens.orEmpty().filter { token -> token.networkId in networkIds },
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex(accountDTO.derivationIndex).getOrNull(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId)
|
||||
val response = userTokensResponseStore.getSyncOrNull(userWalletId = userWallet.walletId)
|
||||
?: return emptyMap()
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token -> token.networkId in networkIds },
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
.groupBy { it.network.id.rawId }
|
||||
}
|
||||
|
||||
private fun getSingleWalletCurrencies(userWallet: UserWallet.Cold): SingleWalletCurrencies {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.blockchainsdk.utils.toCoinId
|
|||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import timber.log.Timber
|
||||
|
|
@ -24,19 +25,31 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
.first { it.id.value == currencyId }
|
||||
}
|
||||
|
||||
fun createCurrencies(response: UserTokensResponse, userWallet: UserWallet): List<CryptoCurrency> {
|
||||
return createCurrencies(tokens = response.tokens, userWallet = userWallet)
|
||||
fun createCurrencies(
|
||||
response: UserTokensResponse,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): List<CryptoCurrency> {
|
||||
return createCurrencies(tokens = response.tokens, userWallet = userWallet, accountIndex = accountIndex)
|
||||
}
|
||||
|
||||
fun createCurrencies(tokens: List<UserTokensResponse.Token>, userWallet: UserWallet): List<CryptoCurrency> {
|
||||
fun createCurrencies(
|
||||
tokens: List<UserTokensResponse.Token>,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): List<CryptoCurrency> {
|
||||
return tokens
|
||||
.asSequence()
|
||||
.mapNotNull { createCurrency(it, userWallet) }
|
||||
.mapNotNull { createCurrency(it, userWallet, accountIndex) }
|
||||
.distinctBy(CryptoCurrency::id)
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun createCurrency(responseToken: UserTokensResponse.Token, userWallet: UserWallet): CryptoCurrency? {
|
||||
fun createCurrency(
|
||||
responseToken: UserTokensResponse.Token,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): CryptoCurrency? {
|
||||
var blockchain = Blockchain.fromNetworkId(responseToken.networkId)
|
||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to find a blockchain with the network ID: ${responseToken.networkId}")
|
||||
|
|
@ -49,9 +62,9 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
|
||||
val sdkToken = createSdkToken(responseToken)
|
||||
return if (sdkToken == null) {
|
||||
createCoin(blockchain, responseToken, userWallet)
|
||||
createCoin(blockchain, responseToken, userWallet, accountIndex)
|
||||
} else {
|
||||
createToken(blockchain, sdkToken, responseToken.derivationPath, userWallet)
|
||||
createToken(blockchain, sdkToken, responseToken.derivationPath, userWallet, accountIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,11 +84,13 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
blockchain: Blockchain,
|
||||
responseToken: UserTokensResponse.Token,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): CryptoCurrency.Coin? {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = responseToken.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
return CryptoCurrency.Coin(
|
||||
|
|
@ -106,11 +121,13 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
sdkToken: Token,
|
||||
responseDerivationPath: String?,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): CryptoCurrency.Token? {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = responseDerivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
val id = getTokenId(network, sdkToken)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.wallets.derivations.derivationStyleProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO: [REDACTED_JIRA]
|
||||
class UserTokensResponseFactory @Inject constructor() {
|
||||
|
||||
fun createUserTokensResponse(
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.domain.card.common.extensions.canHandleToken
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.derivations.DerivationStyleProvider
|
||||
import com.tangem.domain.wallets.derivations.derivationStyleProvider
|
||||
import com.tangem.lib.crypto.derivation.toMutable
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -21,6 +23,7 @@ import javax.inject.Inject
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Suppress("LargeClass")
|
||||
class NetworkFactory @Inject constructor(
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) {
|
||||
|
|
@ -32,13 +35,19 @@ class NetworkFactory @Inject constructor(
|
|||
* @param extraDerivationPath extra derivation path
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
fun create(blockchain: Blockchain, extraDerivationPath: String?, userWallet: UserWallet): Network? {
|
||||
fun create(
|
||||
blockchain: Blockchain,
|
||||
extraDerivationPath: String?,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): Network? {
|
||||
return create(
|
||||
blockchain = blockchain,
|
||||
derivationPath = createDerivationPath(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
cardDerivationStyleProvider = userWallet.derivationStyleProvider,
|
||||
accountIndex = accountIndex,
|
||||
),
|
||||
canHandleTokens = userWallet.canHandleToken(
|
||||
blockchain = blockchain,
|
||||
|
|
@ -80,6 +89,7 @@ class NetworkFactory @Inject constructor(
|
|||
extraDerivationPath: String?,
|
||||
derivationStyleProvider: DerivationStyleProvider?,
|
||||
canHandleTokens: Boolean,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): Network? {
|
||||
return create(
|
||||
blockchain = blockchain,
|
||||
|
|
@ -87,6 +97,7 @@ class NetworkFactory @Inject constructor(
|
|||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
cardDerivationStyleProvider = derivationStyleProvider,
|
||||
accountIndex = accountIndex,
|
||||
),
|
||||
canHandleTokens = canHandleTokens,
|
||||
)
|
||||
|
|
@ -134,10 +145,11 @@ class NetworkFactory @Inject constructor(
|
|||
blockchain: Blockchain,
|
||||
extraDerivationPath: String?,
|
||||
cardDerivationStyleProvider: DerivationStyleProvider?,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): Network.DerivationPath {
|
||||
if (cardDerivationStyleProvider == null) return Network.DerivationPath.None
|
||||
|
||||
val defaultDerivationPath = getDefaultDerivationPath(blockchain, cardDerivationStyleProvider)
|
||||
val defaultDerivationPath = getDefaultDerivationPath(blockchain, cardDerivationStyleProvider, accountIndex)
|
||||
|
||||
return if (extraDerivationPath.isNullOrBlank()) {
|
||||
if (defaultDerivationPath.isNullOrBlank()) {
|
||||
|
|
@ -146,10 +158,11 @@ class NetworkFactory @Inject constructor(
|
|||
Network.DerivationPath.Card(defaultDerivationPath)
|
||||
}
|
||||
} else {
|
||||
if (extraDerivationPath == defaultDerivationPath) {
|
||||
Network.DerivationPath.Card(defaultDerivationPath)
|
||||
} else {
|
||||
val isMainIndexOrNull = accountIndex == null || accountIndex == DerivationIndex.Main
|
||||
if (extraDerivationPath != defaultDerivationPath && isMainIndexOrNull) {
|
||||
Network.DerivationPath.Custom(extraDerivationPath)
|
||||
} else {
|
||||
Network.DerivationPath.Card(extraDerivationPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,8 +170,19 @@ class NetworkFactory @Inject constructor(
|
|||
private fun getDefaultDerivationPath(
|
||||
blockchain: Blockchain,
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
accountIndex: DerivationIndex?,
|
||||
): String? {
|
||||
return blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())?.rawPath
|
||||
val default = blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())
|
||||
?: return null
|
||||
|
||||
return if (accountIndex == null || accountIndex == DerivationIndex.Main) {
|
||||
default
|
||||
} else {
|
||||
default.toMutable()
|
||||
.replaceAccountNode(value = accountIndex.value.toLong(), blockchain = blockchain)
|
||||
.apply()
|
||||
}
|
||||
.rawPath
|
||||
}
|
||||
|
||||
private fun getNetworkStandardType(blockchain: Blockchain): Network.StandardType {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ android {
|
|||
dependencies {
|
||||
|
||||
/** Project - Domain */
|
||||
implementation(projects.domain.account)
|
||||
implementation(projects.domain.demo)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.manageTokens)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@ import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
|
|||
import com.tangem.data.managetokens.utils.ManagedCryptoCurrencyFactory
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.domain.card.common.extensions.*
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
|
|
@ -51,10 +53,15 @@ internal class DefaultManageTokensRepository(
|
|||
private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val walletAccountsFetcher: WalletAccountsFetcher,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
networkFactory: NetworkFactory,
|
||||
) : ManageTokensRepository {
|
||||
|
||||
private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory(networkFactory, excludedBlockchains)
|
||||
private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory(
|
||||
networkFactory = networkFactory,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
accountsFeatureToggles = accountsFeatureToggles,
|
||||
)
|
||||
private val userTokensResponseFactory = UserTokensResponseFactory()
|
||||
|
||||
// region getTokenListBatchFlow
|
||||
|
|
@ -82,7 +89,10 @@ internal class DefaultManageTokensRepository(
|
|||
val userWallet = request.params.userWalletId?.let(userWalletsStore::getSyncStrict)
|
||||
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isTestCard) {
|
||||
fetchTestnetCurrencies(userWallet, request)
|
||||
when (val params = request.params) {
|
||||
is ManageTokensListConfig.Account -> fetchTestnetCurrencies(userWallet, params)
|
||||
is ManageTokensListConfig.Wallet -> fetchTestnetCurrenciesLegacy(userWallet, params)
|
||||
}
|
||||
} else {
|
||||
fetchCurrencies(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -126,17 +136,73 @@ internal class DefaultManageTokensRepository(
|
|||
coins = coinsResponse.coins.filterNot { l2BlockchainsCoinIds.contains(it.id) },
|
||||
)
|
||||
|
||||
val tokensResponse = request.params.userWalletId?.let { userWalletId ->
|
||||
when (val params = request.params) {
|
||||
is ManageTokensListConfig.Account -> {
|
||||
fetchUserTokens(userWallet, userWalletId, params, loadUserTokensFromRemote)
|
||||
}
|
||||
is ManageTokensListConfig.Wallet -> {
|
||||
fetchUserTokensLegacy(userWallet, userWalletId, loadUserTokensFromRemote)
|
||||
}
|
||||
val items = when (val params = request.params) {
|
||||
is ManageTokensListConfig.Account -> createManagedCryptoCurrencyList(
|
||||
params = params,
|
||||
userWallet = userWallet,
|
||||
isFirstBatchFetching = isFirstBatchFetching,
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
query = query,
|
||||
updatedCoinsResponse = updatedCoinsResponse,
|
||||
)
|
||||
is ManageTokensListConfig.Wallet -> createManagedCryptoCurrencyListLegacy(
|
||||
params = params,
|
||||
userWallet = userWallet,
|
||||
isFirstBatchFetching = isFirstBatchFetching,
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
query = query,
|
||||
updatedCoinsResponse = updatedCoinsResponse,
|
||||
)
|
||||
}
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
data = items,
|
||||
empty = items.isEmpty(),
|
||||
last = items.size < request.limit,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun createManagedCryptoCurrencyList(
|
||||
params: ManageTokensListConfig.Account,
|
||||
userWallet: UserWallet?,
|
||||
isFirstBatchFetching: Boolean,
|
||||
loadUserTokensFromRemote: Boolean,
|
||||
query: String?,
|
||||
updatedCoinsResponse: CoinsResponse,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val response = params.userWalletId?.let { userWalletId ->
|
||||
if (loadUserTokensFromRemote && userWallet != null) {
|
||||
runCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
|
||||
} else {
|
||||
walletAccountsFetcher.getSaved(userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
val accountId = when {
|
||||
params.accountId == null -> null
|
||||
loadUserTokensFromRemote -> {
|
||||
AccountId.forCryptoPortfolio(
|
||||
userWalletId = requireNotNull(params.accountId).userWalletId,
|
||||
derivationIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
else -> requireNotNull(params.accountId)
|
||||
}
|
||||
|
||||
val accountDTO = if (response != null && accountId != null) {
|
||||
response.accounts.firstOrNull { it.id == accountId.value }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val tokensResponse = response?.let {
|
||||
UserTokensResponse(
|
||||
group = response.wallet.group,
|
||||
sort = response.wallet.sort,
|
||||
tokens = accountDTO?.tokens.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
val isCreateWithCustom = isFirstBatchFetching &&
|
||||
tokensResponse != null &&
|
||||
userWallet != null &&
|
||||
|
|
@ -147,69 +213,58 @@ internal class DefaultManageTokensRepository(
|
|||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
|
||||
)
|
||||
} else {
|
||||
managedCryptoCurrencyFactory.create(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
|
||||
)
|
||||
}
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
data = items,
|
||||
empty = items.isEmpty(),
|
||||
last = items.size < request.limit,
|
||||
)
|
||||
return items
|
||||
}
|
||||
|
||||
private suspend fun fetchUserTokens(
|
||||
private suspend fun createManagedCryptoCurrencyListLegacy(
|
||||
params: ManageTokensListConfig.Wallet,
|
||||
userWallet: UserWallet?,
|
||||
userWalletId: UserWalletId,
|
||||
params: ManageTokensListConfig.Account,
|
||||
isFirstBatchFetching: Boolean,
|
||||
loadUserTokensFromRemote: Boolean,
|
||||
): UserTokensResponse? {
|
||||
val accountId = when {
|
||||
params.accountId == null -> {
|
||||
return null
|
||||
}
|
||||
loadUserTokensFromRemote -> {
|
||||
AccountId.forCryptoPortfolio(userWalletId = userWalletId, derivationIndex = DerivationIndex.Main)
|
||||
}
|
||||
else -> requireNotNull(params.accountId)
|
||||
}
|
||||
|
||||
val response = if (loadUserTokensFromRemote && userWallet != null) {
|
||||
runCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
|
||||
} else {
|
||||
walletAccountsFetcher.getSaved(userWalletId)
|
||||
}
|
||||
|
||||
val account = response?.accounts?.firstOrNull { it.id == accountId.value }
|
||||
?: return null
|
||||
|
||||
return UserTokensResponse(
|
||||
group = response.wallet.group,
|
||||
sort = response.wallet.sort,
|
||||
tokens = account.tokens.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchUserTokensLegacy(
|
||||
userWallet: UserWallet?,
|
||||
userWalletId: UserWalletId,
|
||||
loadUserTokensFromRemote: Boolean,
|
||||
): UserTokensResponse? {
|
||||
return if (loadUserTokensFromRemote && userWallet != null) {
|
||||
safeApiCall(
|
||||
call = { tangemTechApi.getUserTokens(userWalletId.stringValue).bind() },
|
||||
onError = {
|
||||
query: String?,
|
||||
updatedCoinsResponse: CoinsResponse,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val tokensResponse = params.userWalletId?.let { userWalletId ->
|
||||
if (loadUserTokensFromRemote && userWallet != null) {
|
||||
safeApiCall({ tangemTechApi.getUserTokens(userWalletId.stringValue).bind() }) {
|
||||
// save tokens response only if loadUserTokensFromRemote is true and it means onboarding call
|
||||
createAndSaveDefaultUserTokensResponse(userWallet = userWallet)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
getSavedUserTokensResponseSync(userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
val isCreateWithCustom = isFirstBatchFetching &&
|
||||
tokensResponse != null &&
|
||||
userWallet != null &&
|
||||
query == null
|
||||
|
||||
return if (isCreateWithCustom) {
|
||||
managedCryptoCurrencyFactory.createWithCustomTokens(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = null,
|
||||
)
|
||||
} else {
|
||||
getSavedUserTokensResponseSync(userWalletId)
|
||||
managedCryptoCurrencyFactory.create(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,9 +276,59 @@ internal class DefaultManageTokensRepository(
|
|||
|
||||
private suspend fun fetchTestnetCurrencies(
|
||||
userWallet: UserWallet,
|
||||
request: Request<ManageTokensListConfig>,
|
||||
params: ManageTokensListConfig.Account,
|
||||
): BatchFetchResult.Success<List<ManagedCryptoCurrency>> {
|
||||
val searchText = request.params.searchText
|
||||
val searchText = params.searchText
|
||||
val testnetTokensConfig = testnetTokensStorage.getConfig()
|
||||
|
||||
val response = params.userWalletId?.let { userWalletId ->
|
||||
walletAccountsFetcher.getSaved(userWalletId)
|
||||
}
|
||||
|
||||
val accountId = params.accountId
|
||||
|
||||
val accountDTO = if (response != null && accountId != null) {
|
||||
response.accounts.firstOrNull { it.id == accountId.value }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val tokensResponse = response?.let {
|
||||
UserTokensResponse(
|
||||
group = response.wallet.group,
|
||||
sort = response.wallet.sort,
|
||||
tokens = accountDTO?.tokens.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
val items = managedCryptoCurrencyFactory.createTestnetWithCustomTokens(
|
||||
testnetTokensConfig = if (!searchText.isNullOrBlank()) {
|
||||
testnetTokensConfig.copy(
|
||||
tokens = testnetTokensConfig.tokens.filter { token ->
|
||||
token.symbol.contains(other = searchText, ignoreCase = true) ||
|
||||
token.name.contains(other = searchText, ignoreCase = true)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
testnetTokensConfig
|
||||
},
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
data = items,
|
||||
empty = items.isEmpty(),
|
||||
last = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchTestnetCurrenciesLegacy(
|
||||
userWallet: UserWallet,
|
||||
params: ManageTokensListConfig.Wallet,
|
||||
): BatchFetchResult.Success<List<ManagedCryptoCurrency>> {
|
||||
val searchText = params.searchText
|
||||
val testnetTokensConfig = testnetTokensStorage.getConfig()
|
||||
|
||||
val items = managedCryptoCurrencyFactory.createTestnetWithCustomTokens(
|
||||
|
|
@ -239,6 +344,7 @@ internal class DefaultManageTokensRepository(
|
|||
},
|
||||
tokensResponse = getSavedUserTokensResponseSync(userWallet.walletId),
|
||||
userWallet = userWallet,
|
||||
accountIndex = null,
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
|
|||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -39,6 +40,7 @@ internal object ManageTokensDataModule {
|
|||
excludedBlockchains: ExcludedBlockchains,
|
||||
cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
|
||||
networkFactory: NetworkFactory,
|
||||
accountsFeatureToggles: AccountsFeatureToggles,
|
||||
walletAccountsFetcher: WalletAccountsFetcher,
|
||||
): ManageTokensRepository {
|
||||
return DefaultManageTokensRepository(
|
||||
|
|
@ -52,6 +54,7 @@ internal object ManageTokensDataModule {
|
|||
cardCryptoCurrencyFactory = cardCryptoCurrencyFactory,
|
||||
networkFactory = networkFactory,
|
||||
dispatchers = dispatchers,
|
||||
accountsFeatureToggles = accountsFeatureToggles,
|
||||
walletAccountsFetcher = walletAccountsFetcher,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ import com.tangem.data.common.network.NetworkFactory
|
|||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.config.testnet.models.TestnetTokensConfig
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.extensions.canHandleToken
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -26,15 +28,17 @@ import timber.log.Timber
|
|||
internal class ManagedCryptoCurrencyFactory(
|
||||
private val networkFactory: NetworkFactory,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) {
|
||||
|
||||
fun create(
|
||||
coinsResponse: CoinsResponse,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
userWallet: UserWallet?,
|
||||
accountIndex: DerivationIndex?,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
return coinsResponse.coins.mapNotNull { coin ->
|
||||
createToken(coin, tokensResponse, coinsResponse.imageHost, userWallet)
|
||||
createToken(coin, tokensResponse, coinsResponse.imageHost, userWallet, accountIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,9 +46,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
coinsResponse: CoinsResponse,
|
||||
tokensResponse: UserTokensResponse,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val customTokens = createCustomTokens(tokensResponse, userWallet)
|
||||
val tokens = create(coinsResponse, tokensResponse, userWallet)
|
||||
val customTokens = createCustomTokens(tokensResponse, userWallet, accountIndex)
|
||||
val tokens = create(coinsResponse, tokensResponse, userWallet, accountIndex)
|
||||
|
||||
return customTokens + tokens
|
||||
}
|
||||
|
|
@ -53,9 +58,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
testnetTokensConfig: TestnetTokensConfig,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val customTokens = tokensResponse
|
||||
?.let { createCustomTokens(it, userWallet) }
|
||||
?.let { createCustomTokens(it, userWallet, accountIndex) }
|
||||
?: emptyList()
|
||||
val testnetTokens = testnetTokensConfig.tokens.map { testnetToken ->
|
||||
ManagedCryptoCurrency.Token(
|
||||
|
|
@ -69,9 +75,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
contractAddress = network.address,
|
||||
decimals = network.decimalCount,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
} ?: emptyList(),
|
||||
addedIn = findAddedInNetworks(testnetToken.id, tokensResponse, userWallet),
|
||||
addedIn = findAddedInNetworks(testnetToken.id, tokensResponse, userWallet, accountIndex),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -81,28 +88,47 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
private fun createCustomTokens(
|
||||
tokensResponse: UserTokensResponse,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): List<ManagedCryptoCurrency> = tokensResponse.tokens
|
||||
.mapNotNull { token ->
|
||||
maybeCreateCustomToken(token, userWallet)
|
||||
maybeCreateCustomToken(token, userWallet, accountIndex)
|
||||
}
|
||||
|
||||
private fun maybeCreateCustomToken(
|
||||
token: UserTokensResponse.Token,
|
||||
userWallet: UserWallet,
|
||||
accountIndex: DerivationIndex?,
|
||||
): ManagedCryptoCurrency? {
|
||||
val blockchain = Blockchain.fromNetworkId(token.networkId)
|
||||
?.takeUnless { it in excludedBlockchains }
|
||||
?: return null
|
||||
|
||||
if (!checkIsCustomToken(token, blockchain, userWallet.derivationStyleProvider)) {
|
||||
return null
|
||||
val network = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
if (!checkIsCustomToken(token, network.derivationPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
network
|
||||
} else {
|
||||
if (!checkIsCustomToken(token, blockchain, userWallet.derivationStyleProvider)) {
|
||||
return null
|
||||
}
|
||||
|
||||
networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
}
|
||||
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
val contractAddress = token.contractAddress
|
||||
|
||||
return if (contractAddress.isNullOrBlank()) {
|
||||
|
|
@ -135,6 +161,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
tokensResponse: UserTokensResponse?,
|
||||
imageHost: String?,
|
||||
userWallet: UserWallet?,
|
||||
accountIndex: DerivationIndex?,
|
||||
): ManagedCryptoCurrency? {
|
||||
if (coinResponse.networks.isEmpty() || !coinResponse.active) return null
|
||||
|
||||
|
|
@ -146,6 +173,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
contractAddress = network.contractAddress,
|
||||
decimals = network.decimalCount?.toInt(),
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
}
|
||||
.ifEmpty { return null }
|
||||
|
|
@ -156,7 +184,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
symbol = coinResponse.symbol,
|
||||
iconUrl = getIconUrl(coinResponse.id, imageHost),
|
||||
availableNetworks = availableNetworks,
|
||||
addedIn = findAddedInNetworks(coinResponse.id, tokensResponse, userWallet),
|
||||
addedIn = findAddedInNetworks(coinResponse.id, tokensResponse, userWallet, accountIndex),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +194,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
decimals: Int?,
|
||||
userWallet: UserWallet?,
|
||||
extraDerivationPath: String? = null,
|
||||
accountIndex: DerivationIndex?,
|
||||
): SourceNetwork? {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
?.takeUnless { it in excludedBlockchains }
|
||||
|
|
@ -176,6 +205,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
extraDerivationPath = extraDerivationPath,
|
||||
derivationStyleProvider = userWallet?.derivationStyleProvider,
|
||||
canHandleTokens = userWallet?.canHandleToken(blockchain, excludedBlockchains) == true,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
return when {
|
||||
|
|
@ -205,6 +235,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
currencyId: String,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
userWallet: UserWallet?,
|
||||
accountIndex: DerivationIndex?,
|
||||
): Set<Network> {
|
||||
if (tokensResponse == null) return emptySet()
|
||||
|
||||
|
|
@ -219,6 +250,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
extraDerivationPath = token.derivationPath,
|
||||
derivationStyleProvider = userWallet?.derivationStyleProvider,
|
||||
canHandleTokens = userWallet?.canHandleToken(blockchain, excludedBlockchains) != false,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
@ -237,6 +269,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
): Boolean = token.id.isNullOrBlank() ||
|
||||
checkIsCustomDerivationPath(token.derivationPath, blockchain, derivationStyleProvider)
|
||||
|
||||
private fun checkIsCustomToken(token: UserTokensResponse.Token, derivationPath: Network.DerivationPath): Boolean {
|
||||
return token.id.isNullOrBlank() || derivationPath is Network.DerivationPath.Custom
|
||||
}
|
||||
|
||||
private fun checkIsCustomDerivationPath(
|
||||
derivationPath: String?,
|
||||
blockchain: Blockchain,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.tangem.datasource.local.datastore.RuntimeStateStore
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.pagination.*
|
||||
|
|
@ -250,6 +251,7 @@ internal class DefaultMarketsTokenRepository(
|
|||
userWalletId: UserWalletId,
|
||||
token: TokenMarketParams,
|
||||
network: TokenMarketInfo.Network,
|
||||
accountIndex: DerivationIndex?,
|
||||
): CryptoCurrency? {
|
||||
val userWallet = userWalletsStore.getSyncOrNull(userWalletId) ?: error("UserWalletId [$userWalletId] not found")
|
||||
val blockchain = Blockchain.fromNetworkId(network.networkId) ?: error("Unknown network [${network.networkId}]")
|
||||
|
|
@ -259,12 +261,14 @@ internal class DefaultMarketsTokenRepository(
|
|||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
} else {
|
||||
val currencyNetwork = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
cryptoCurrencyFactory.createToken(
|
||||
|
|
|
|||
|
|
@ -90,6 +90,14 @@ class ManageCryptoCurrenciesUseCase(
|
|||
derivePublicKeys(userWalletId = userWalletId, currencies = modifiedCurrencyList.added)
|
||||
|
||||
parallelUpdatingScope.launch {
|
||||
/*
|
||||
* If only removal of currencies happened, we need to sync tokens. Otherwise, tokens will be synced
|
||||
* when balances are refreshed for added currencies.
|
||||
*/
|
||||
if (modifiedCurrencyList.added.isEmpty() && modifiedCurrencyList.removed.isNotEmpty()) {
|
||||
launch { accountsCRUDRepository.syncTokens(userWalletId) }
|
||||
}
|
||||
|
||||
refreshBalances(userWalletId = userWalletId, currencies = modifiedCurrencyList.added)
|
||||
refreshExpress(userWalletId = userWalletId, currencies = modifiedCurrencyList.total)
|
||||
clearMetadata(userWalletId = userWalletId, currencies = modifiedCurrencyList.removed)
|
||||
|
|
@ -119,7 +127,7 @@ class ManageCryptoCurrenciesUseCase(
|
|||
|
||||
val tokenToAdd = findToken(userWalletId, contractAddress, networkId)
|
||||
|
||||
val modifiedCurrencyList = account.cryptoCurrencies.modify(add = listOf(tokenToAdd), remove = emptyList())
|
||||
val modifiedCurrencyList = account.cryptoCurrencies.modify(add = listOf(tokenToAdd))
|
||||
|
||||
saveAccount(account = account.copy(cryptoCurrencies = modifiedCurrencyList.total.toSet()))
|
||||
|
||||
|
|
@ -143,7 +151,7 @@ class ManageCryptoCurrenciesUseCase(
|
|||
|
||||
private fun Set<CryptoCurrency>.modify(
|
||||
add: List<CryptoCurrency>,
|
||||
remove: List<CryptoCurrency>,
|
||||
remove: List<CryptoCurrency> = emptyList(),
|
||||
): ModifiedCurrencyList {
|
||||
val mutableCurrencies = this.toMutableList()
|
||||
val added = mutableListOf<CryptoCurrency>()
|
||||
|
|
@ -176,9 +184,8 @@ class ManageCryptoCurrenciesUseCase(
|
|||
|
||||
remove.groupByNetwork(valuePredicate = existingCurrenciesById::containsKey)
|
||||
.forEach { (network, currenciesById) ->
|
||||
val coinTempId = TempID(network)
|
||||
|
||||
if (currenciesById.containsKey(coinTempId)) {
|
||||
val isCoinBeingRemoved = currenciesById.any { it.value is CryptoCurrency.Coin }
|
||||
if (isCoinBeingRemoved) {
|
||||
val existingNetworkCurrenciesCount = mutableCurrencies.count { it.network == network }
|
||||
|
||||
if (existingNetworkCurrenciesCount != currenciesById.size) {
|
||||
|
|
@ -306,7 +313,7 @@ class ManageCryptoCurrenciesUseCase(
|
|||
private suspend fun clearMetadata(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
if (currencies.isEmpty()) return
|
||||
|
||||
return coroutineScope {
|
||||
coroutineScope {
|
||||
listOf(
|
||||
launch { networksCleaner(userWalletId = userWalletId, currencies = currencies) },
|
||||
launch { clearStaking(userWalletId = userWalletId, currencies = currencies) },
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.markets
|
||||
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
|
|
@ -11,11 +12,13 @@ class GetTokenMarketCryptoCurrency(
|
|||
userWalletId: UserWalletId,
|
||||
tokenMarketParams: TokenMarketParams,
|
||||
network: TokenMarketInfo.Network,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): CryptoCurrency? {
|
||||
return marketsTokenRepository.createCryptoCurrency(
|
||||
userWalletId = userWalletId,
|
||||
token = tokenMarketParams,
|
||||
network = network,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.markets.repositories
|
||||
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -45,6 +46,7 @@ interface MarketsTokenRepository {
|
|||
userWalletId: UserWalletId,
|
||||
token: TokenMarketParams,
|
||||
network: TokenMarketInfo.Network,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
): CryptoCurrency?
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -95,6 +95,14 @@ data class Network(
|
|||
data object None : DerivationPath() {
|
||||
override val value: String? get() = null
|
||||
}
|
||||
|
||||
fun copySealed(value: String): DerivationPath {
|
||||
return when (this) {
|
||||
is Card -> Card(value)
|
||||
is Custom -> Custom(value)
|
||||
None -> None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import com.tangem.domain.account.producer.SingleAccountProducer
|
|||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.managetokens.CheckIsCurrencyNotAddedUseCase
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
|
|
@ -27,7 +29,13 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
|||
|
||||
suspend fun addCryptoCurrenciesUseCase(currency: CryptoCurrency): Either<Throwable, Unit> = when (mode) {
|
||||
is AddCustomTokenMode.Account -> {
|
||||
manageCryptoCurrenciesUseCase(accountId = mode.accountId, add = currency)
|
||||
manageCryptoCurrenciesUseCase(
|
||||
accountId = AccountId.forCryptoPortfolio(
|
||||
userWalletId = mode.userWalletId,
|
||||
derivationIndex = DerivationIndex.Main,
|
||||
),
|
||||
add = currency,
|
||||
)
|
||||
}
|
||||
is AddCustomTokenMode.Wallet -> {
|
||||
addCryptoCurrenciesUseCase.invoke(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.ui.message.ToastMessage
|
|||
import com.tangem.domain.account.status.usecase.GetCryptoCurrencyActionsUseCaseV2
|
||||
import com.tangem.domain.markets.GetTokenMarketCryptoCurrency
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -243,6 +244,7 @@ internal class AddToPortfolioModel @Inject constructor(
|
|||
cryptoCurrency = createCryptoCurrency(
|
||||
userWallet = selectedPortfolio.userWallet,
|
||||
network = selectedNetwork,
|
||||
account = selectedPortfolio.account,
|
||||
) ?: return@transform null,
|
||||
selectedNetwork = selectedNetwork,
|
||||
availableMoreNetwork = !selectedPortfolio.account.isSingleNetwork,
|
||||
|
|
@ -254,10 +256,12 @@ internal class AddToPortfolioModel @Inject constructor(
|
|||
private suspend fun createCryptoCurrency(
|
||||
userWallet: UserWallet,
|
||||
network: TokenMarketInfo.Network,
|
||||
account: AvailableToAddAccount,
|
||||
): CryptoCurrency? = getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
tokenMarketParams = addToPortfolioManager.token,
|
||||
network = network,
|
||||
accountIndex = (account.account as? AccountStatus.CryptoPortfolio)?.account?.derivationIndex,
|
||||
)
|
||||
|
||||
private fun routeToNetworkSelector(portfolio: SelectedPortfolio): AddToPortfolioRoutes.NetworkSelector {
|
||||
|
|
|
|||
|
|
@ -66,12 +66,11 @@ internal class AddTokenModel @Inject constructor(
|
|||
val blockchainNames = listOf(selectedNetwork.selectedNetwork)
|
||||
.mapNotNull { BlockchainUtils.getNetworkInfo(it.networkId)?.name }
|
||||
analyticsEventHandler.send(analyticsEventBuilder.addToPortfolioContinue(blockchainNames))
|
||||
|
||||
val cryptoCurrency = selectedNetwork.cryptoCurrency
|
||||
val accountId = selectedPortfolio.account.account.account.accountId
|
||||
manageCryptoCurrenciesUseCase(
|
||||
accountId = accountId,
|
||||
add = cryptoCurrency,
|
||||
)
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = cryptoCurrency)
|
||||
|
||||
val status = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = accountId.userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue