Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-21 18:58:30 +05:00
parent e63ca27981
commit 1b4df19930
5 changed files with 61 additions and 53 deletions

View file

@ -1,6 +1,7 @@
package com.tangem.data.tokens.repository
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.address.AddressType
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.tokens.utils.CardCryptoCurrenciesFactory
import com.tangem.data.tokens.utils.NetworkStatusFactory
@ -77,6 +78,21 @@ internal class DefaultNetworksRepository(
return blockchain == Blockchain.Aptos
}
override suspend fun getNetworkAddresses(userWalletId: UserWalletId, network: Network): List<String> {
// Get list of currencies matching [network]
val currencies = getCurrencies(userWalletId)
.filter { currency -> network.id == currency.network.id }
// There is no currencies matching given [networks] in [userWalletId]
if (currencies.toList().isEmpty()) return emptyList()
return currencies.toList().map { currency ->
walletManagersFacade.getAddresses(userWalletId, currency.network)
.firstOrNull { it.type == AddressType.Default }
?.value.orEmpty()
}
}
private suspend fun fetchNetworksStatusesIfCacheExpired(
userWalletId: UserWalletId,
networks: Set<Network>,
@ -174,11 +190,16 @@ internal class DefaultNetworksRepository(
}
private suspend fun getCurrencies(userWalletId: UserWalletId, networks: Set<Network>): Sequence<CryptoCurrency> {
val currencies = getCurrencies(userWalletId)
return currencies.filter { networks.contains(it.network) }
}
private suspend fun getCurrencies(userWalletId: UserWalletId): Sequence<CryptoCurrency> {
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
"Unable to find user wallet with provided ID: $userWalletId"
}
val currencies = if (userWallet.isMultiCurrency) {
return if (userWallet.isMultiCurrency) {
val response = requireNotNull(userTokensStore.getSyncOrNull(userWalletId)) {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
}
@ -194,8 +215,6 @@ internal class DefaultNetworksRepository(
sequenceOf(currency)
}
}
return currencies.filter { networks.contains(it.network) }
}
private suspend fun invalidateCacheKeyIfNeeded(

View file

@ -1,27 +1,14 @@
package com.tangem.domain.tokens
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class GetNetworkAddressesUseCase(
internal val networksRepository: NetworksRepository,
) {
operator fun invoke(userWalletId: UserWalletId, network: Network): Flow<List<String>> =
networksRepository.getNetworkStatusesUpdates(userWalletId, setOf(network))
.map { networkStatuses ->
networkStatuses.filter { it.network.id == network.id }
.map { networkStatus ->
when (val status = networkStatus.value) {
is NetworkStatus.NoAccount -> status.address.defaultAddress.value
is NetworkStatus.Unreachable -> status.address?.defaultAddress?.value.orEmpty()
is NetworkStatus.Verified -> status.address.defaultAddress.value
else -> ""
}
}
}
suspend fun invokeSync(userWalletId: UserWalletId, network: Network): List<String> {
return networksRepository.getNetworkAddresses(userWalletId, network)
}
}

View file

@ -45,4 +45,6 @@ interface NetworksRepository {
): Set<NetworkStatus>
fun isNeedToCreateAccountWithoutReserve(network: Network): Boolean
suspend fun getNetworkAddresses(userWalletId: UserWalletId, network: Network): List<String>
}

View file

@ -9,7 +9,6 @@ import com.tangem.features.send.impl.presentation.state.recipient.utils.emptyLis
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.flow.filter
internal class SendRecipientWalletListConverter :
Converter<List<AvailableWallet?>, PersistentList<SendRecipientListContent>> {
@ -24,19 +23,25 @@ internal class SendRecipientWalletListConverter :
return this.filterNotNull()
.filter { it.address.isNotBlank() }
.groupBy { item -> item.name }
.values.map {
it.mapIndexed { index, item ->
val name = if (it.size > 1) {
"${item.name} ${index.inc()}"
} else {
item.name
.values.map { wallets ->
val groupedByWallet = wallets.groupBy { it.userWalletId }
var i = 0
groupedByWallet
.flatMap { item ->
item.value.map { wallet ->
val name = if (groupedByWallet.size > 1) {
"${wallet.name} ${++i}"
} else {
wallet.name
}
SendRecipientListContent(
id = "${WALLET_KEY_TAG}${walletsCounter++}",
title = TextReference.Str(wallet.address),
subtitle = TextReference.Str(name),
)
}
}
SendRecipientListContent(
id = "${WALLET_KEY_TAG}${walletsCounter++}",
title = TextReference.Str(item.address),
subtitle = TextReference.Str(name),
)
}
}
.flatten()
.toPersistentList()

View file

@ -4,6 +4,7 @@ import android.os.SystemClock
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastDistinctBy
import androidx.lifecycle.*
import arrow.core.Either
import arrow.core.getOrElse
@ -271,6 +272,7 @@ internal class SendViewModel @Inject constructor(
.saveIn(balanceHidingJobHolder)
}
// TODO [REDACTED_JIRA]
private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean, isMultiCurrency: Boolean) {
if (cryptoCurrency is CryptoCurrency.Coin) {
getCurrencyStatusUpdates(
@ -405,43 +407,36 @@ internal class SendViewModel @Inject constructor(
?.toAvailableWallets()
.orEmpty()
}.onSuccess { result ->
combine(*result.toTypedArray()) { it }
.onEach { wallets ->
userWallets = wallets.flatMap { it }.toList()
uiState = stateFactory.onLoadedWalletsList(wallets = userWallets)
}
.flowOn(dispatchers.main)
.launchIn(viewModelScope)
userWallets = result
uiState = stateFactory.onLoadedWalletsList(wallets = userWallets)
}.onFailure {
uiState = stateFactory.onLoadedWalletsList(wallets = emptyList())
}
}
}
private suspend fun List<UserWallet>.toAvailableWallets(): List<Flow<List<AvailableWallet>>> =
private suspend fun List<UserWallet>.toAvailableWallets(): List<AvailableWallet> =
filterNot { it.walletId == userWalletId || it.isLocked }
.mapNotNull { wallet ->
val status = if (!wallet.isMultiCurrency) {
val addresses = if (!wallet.isMultiCurrency) {
getCryptoCurrencyUseCase(wallet.walletId).getOrNull()?.let {
if (it.network.id == cryptoCurrency.network.id) {
getNetworkAddressesUseCase(wallet.walletId, it.network)
getNetworkAddressesUseCase.invokeSync(wallet.walletId, it.network)
} else {
null
}
}
} else {
getNetworkAddressesUseCase(wallet.walletId, cryptoCurrency.network)
getNetworkAddressesUseCase.invokeSync(wallet.walletId, cryptoCurrency.network)
}
status?.map { addresses ->
addresses.map { address ->
AvailableWallet(
name = wallet.name,
address = address,
userWalletId = wallet.walletId,
)
}
}
}
addresses?.map { address ->
AvailableWallet(
name = wallet.name,
address = address,
userWalletId = wallet.walletId,
)
}?.fastDistinctBy { it.address }
}.flatten()
private suspend fun getTxHistory() {
val txHistoryList = getFixedTxHistoryItemsUseCase.getSync(