Updated on 2026-08-14

This commit is contained in:
Tangem 2023-08-08 23:50:09 +03:00
parent eab83c7675
commit 9ce639e080
21 changed files with 110 additions and 113 deletions

View file

@ -37,7 +37,7 @@ internal class DefaultCurrenciesRepository(
override suspend fun saveTokens(
userWalletId: UserWalletId,
currencies: Set<CryptoCurrency>,
currencies: List<CryptoCurrency>,
isGroupedByNetwork: Boolean,
isSortedByBalance: Boolean,
) = withContext(dispatchers.io) {
@ -64,7 +64,7 @@ internal class DefaultCurrenciesRepository(
override fun getMultiCurrencyWalletCurrencies(
userWalletId: UserWalletId,
refresh: Boolean,
): Flow<Set<CryptoCurrency>> = channelFlow {
): Flow<List<CryptoCurrency>> = channelFlow {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
@ -115,7 +115,7 @@ internal class DefaultCurrenciesRepository(
}
}
private fun getMultiCurrencyWalletCurrencies(userWallet: UserWallet): Flow<Set<CryptoCurrency>> {
private fun getMultiCurrencyWalletCurrencies(userWallet: UserWallet): Flow<List<CryptoCurrency>> {
return userTokensStore.get(userWallet.walletId).map { storedTokens ->
responseCurrenciesFactory.createCurrencies(
response = storedTokens,

View file

@ -90,7 +90,7 @@ internal class DefaultNetworksRepository(
val result = walletManagersFacade.update(
userWalletId = userWalletId,
networkId = networkId,
extraTokens = currencies.filterIsInstanceTo(hashSetOf()),
extraTokens = currencies.filterIsInstance<CryptoCurrency.Token>().toSet(),
)
val networkStatus = networkStatusFactory.createNetworkStatus(
networkId = networkId,
@ -103,7 +103,7 @@ internal class DefaultNetworksRepository(
}
}
private suspend fun getCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
private suspend fun getCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
"Unable to find user wallet with provided ID: $userWalletId"
}

View file

@ -12,7 +12,7 @@ import com.tangem.blockchain.common.Token as SdkToken
internal class CardCurrenciesFactory(private val demoConfig: DemoConfig) {
fun createDefaultCoinsForMultiCurrencyCard(card: CardDTO): Set<CryptoCurrency.Coin> {
fun createDefaultCoinsForMultiCurrencyCard(card: CardDTO): List<CryptoCurrency.Coin> {
var blockchains = if (demoConfig.isDemoCardId(card.cardId)) {
demoConfig.demoBlockchains
} else {
@ -23,7 +23,7 @@ internal class CardCurrenciesFactory(private val demoConfig: DemoConfig) {
blockchains = blockchains.mapNotNull { it.getTestnetVersion() }
}
return blockchains.mapNotNull { createCoin(it, card) }.toSet()
return blockchains.mapNotNull { createCoin(it, card) }
}
fun createPrimaryCurrencyForSingleCurrencyCard(scanResponse: ScanResponse): CryptoCurrency {

View file

@ -24,8 +24,8 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
}
}
fun createCurrencies(response: UserTokensResponse, card: CardDTO): Set<CryptoCurrency> {
return response.tokens.mapNotNull { createCurrency(it, card) }.toSet()
fun createCurrencies(response: UserTokensResponse, card: CardDTO): List<CryptoCurrency> {
return response.tokens.mapNotNull { createCurrency(it, card) }
}
private fun createCurrency(responseToken: UserTokensResponse.Token, card: CardDTO): CryptoCurrency? {

View file

@ -7,7 +7,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency
internal class UserTokensResponseFactory {
fun createUserTokensResponse(
currencies: Set<CryptoCurrency>,
currencies: List<CryptoCurrency>,
isGroupedByNetwork: Boolean,
isSortedByBalance: Boolean,
): UserTokensResponse {

View file

@ -5,6 +5,7 @@ import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.ensureNotNull
import arrow.core.toNonEmptyListOrNull
import arrow.core.toNonEmptySetOrNull
import com.tangem.domain.tokens.error.TokenListSortingError
import com.tangem.domain.tokens.model.CryptoCurrency
@ -22,7 +23,7 @@ class ApplyTokenListSortingUseCase(
suspend operator fun invoke(
userWalletId: UserWalletId,
sortedTokensIds: Set<Pair<Network.ID, CryptoCurrency.ID>>,
sortedTokensIds: List<Pair<Network.ID, CryptoCurrency.ID>>,
isGroupedByNetwork: Boolean,
isSortedByBalance: Boolean,
): Either<TokenListSortingError, Unit> {
@ -39,16 +40,16 @@ class ApplyTokenListSortingUseCase(
}
private suspend fun Raise<TokenListSortingError>.sortTokens(
sortedTokensIds: Set<Pair<Network.ID, CryptoCurrency.ID>>,
unsortedTokens: Set<CryptoCurrency>,
): Set<CryptoCurrency> = withContext(dispatchers.default) {
sortedTokensIds: List<Pair<Network.ID, CryptoCurrency.ID>>,
unsortedTokens: List<CryptoCurrency>,
): List<CryptoCurrency> = withContext(dispatchers.default) {
val nonEmptySortedTokensIds = ensureNotNull(sortedTokensIds.toNonEmptySetOrNull()) {
TokenListSortingError.TokenListIsEmpty
}
val sortedTokens = sortedMapOf<Int, CryptoCurrency>()
unsortedTokens.forEach { token ->
unsortedTokens.distinct().forEach { token ->
val index = nonEmptySortedTokensIds.indexOfFirst { (networkId, tokenId) ->
networkId == token.networkId && tokenId == token.id
}
@ -60,12 +61,12 @@ class ApplyTokenListSortingUseCase(
}
}
ensureNotNull(sortedTokens.values.toNonEmptySetOrNull()) {
ensureNotNull(sortedTokens.values.toNonEmptyListOrNull()) {
TokenListSortingError.TokenListIsEmpty
}
}
private suspend fun Raise<TokenListSortingError>.getCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
private suspend fun Raise<TokenListSortingError>.getCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
val tokens = catch(
block = {
currenciesRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh = false).firstOrNull()
@ -73,14 +74,14 @@ class ApplyTokenListSortingUseCase(
catch = { raise(TokenListSortingError.DataError(it)) },
)
return ensureNotNull(tokens?.toNonEmptySetOrNull()) {
return ensureNotNull(tokens?.toNonEmptyListOrNull()) {
TokenListSortingError.TokenListIsEmpty
}
}
private suspend fun Raise<TokenListSortingError>.applySorting(
userWalletId: UserWalletId,
tokens: Set<CryptoCurrency>,
tokens: List<CryptoCurrency>,
isGrouped: Boolean,
isSortedByBalance: Boolean,
) = withContext(dispatchers.io) {

View file

@ -43,7 +43,7 @@ class GetTokenListUseCase(
private fun getTokensStatuses(
userWalletId: UserWalletId,
refresh: Boolean,
): Flow<Either<TokenListError, Set<CryptoCurrencyStatus>>> {
): Flow<Either<TokenListError, List<CryptoCurrencyStatus>>> {
val operations = CurrenciesStatusesOperations(
userWalletId = userWalletId,
refresh = refresh,
@ -58,7 +58,7 @@ class GetTokenListUseCase(
private fun createTokenList(
userWalletId: UserWalletId,
tokens: Set<CryptoCurrencyStatus>,
tokens: List<CryptoCurrencyStatus>,
): Flow<Either<TokenListError, TokenList>> {
val operations = TokenListOperations(
userWalletId = userWalletId,

View file

@ -8,9 +8,9 @@ import com.tangem.domain.tokens.models.Network
* This class encapsulates a collection of cryptocurrency statuses, all of which are part of the same blockchain network.
*
* @property network The blockchain network associated with the group.
* @property currencies A set of cryptocurrency statuses that belong to the network.
* @property currencies A list of cryptocurrency statuses that belong to the network.
*/
data class NetworkGroup(
val network: Network,
val currencies: Set<CryptoCurrencyStatus>,
val currencies: List<CryptoCurrencyStatus>,
)

View file

@ -18,12 +18,12 @@ sealed class TokenList {
/**
* Represents tokens that are grouped by their network.
*
* @property groups A set of network groups containing tokens.
* @property groups A list of network groups containing tokens.
* @property totalFiatBalance The total fiat balance across all groups.
* @property sortedBy The criteria used for sorting the tokens within the groups.
*/
data class GroupedByNetwork(
val groups: Set<NetworkGroup>,
val groups: List<NetworkGroup>,
override val totalFiatBalance: FiatBalance,
override val sortedBy: SortType,
) : TokenList()
@ -31,12 +31,12 @@ sealed class TokenList {
/**
* Represents tokens that are not grouped by any specific criteria.
*
* @property currencies A set of cryptocurrency statuses.
* @property currencies A list of cryptocurrency statuses.
* @property totalFiatBalance The total fiat balance across all currencies.
* @property sortedBy The criteria used for sorting the currencies.
*/
data class Ungrouped(
val currencies: Set<CryptoCurrencyStatus>,
val currencies: List<CryptoCurrencyStatus>,
override val totalFiatBalance: FiatBalance,
override val sortedBy: SortType,
) : TokenList()

View file

@ -33,14 +33,14 @@ internal class CurrenciesStatusesOperations(
)
@OptIn(ExperimentalCoroutinesApi::class)
fun getCurrenciesStatusesFlow(): Flow<Either<Error, Set<CryptoCurrencyStatus>>> {
fun getCurrenciesStatusesFlow(): Flow<Either<Error, List<CryptoCurrencyStatus>>> {
return getMultiCurrencyWalletCurrencies().flatMapMerge flatMap@{ maybeCurrencies ->
val nonEmptyCurrencies = maybeCurrencies.fold(
ifLeft = { error ->
return@flatMap flowOf(error.left())
},
ifRight = { it.toNonEmptySetOrNull() },
) ?: return@flatMap flowOf(emptySet<CryptoCurrencyStatus>().right())
ifRight = { it.toNonEmptyListOrNull() },
) ?: return@flatMap flowOf(emptyList<CryptoCurrencyStatus>().right())
val (networksIds, currenciesIds) = getIds(nonEmptyCurrencies)
@ -96,11 +96,11 @@ internal class CurrenciesStatusesOperations(
}
private fun createCurrenciesStatuses(
currencies: NonEmptySet<CryptoCurrency>,
currencies: NonEmptyList<CryptoCurrency>,
quotes: Set<Quote>,
networkStatuses: Set<NetworkStatus>,
): Set<CryptoCurrencyStatus> {
return currencies.mapTo(hashSetOf()) { token ->
): List<CryptoCurrencyStatus> {
return currencies.map { token ->
val quote = quotes.firstOrNull { it.currencyId == token.id }
val networkStatus = networkStatuses.firstOrNull { it.networkId == token.networkId }
@ -122,9 +122,9 @@ internal class CurrenciesStatusesOperations(
return currencyStatusOperations.createTokenStatus()
}
private fun getMultiCurrencyWalletCurrencies(): Flow<Either<Error, Set<CryptoCurrency>>> {
private fun getMultiCurrencyWalletCurrencies(): Flow<Either<Error, List<CryptoCurrency>>> {
return currenciesRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh)
.map<Set<CryptoCurrency>, Either<Error, Set<CryptoCurrency>>> { it.right() }
.map<List<CryptoCurrency>, Either<Error, List<CryptoCurrency>>> { it.right() }
.catch { emit(Error.DataError(it).left()) }
.onEmpty { emit(Error.EmptyCurrencies.left()) }
}
@ -157,7 +157,7 @@ internal class CurrenciesStatusesOperations(
}
private fun getIds(
currencies: NonEmptySet<CryptoCurrency>,
currencies: NonEmptyList<CryptoCurrency>,
): Pair<NonEmptySet<Network.ID>, NonEmptySet<CryptoCurrency.ID>> {
val currencyIdToNetworkId = currencies.associate { currency ->
currency.id to currency.networkId

View file

@ -1,12 +1,12 @@
package com.tangem.domain.tokens.operations
import arrow.core.NonEmptySet
import arrow.core.NonEmptyList
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.TokenList
import java.math.BigDecimal
internal class TokenListFiatBalanceOperations(
private val currencies: NonEmptySet<CryptoCurrencyStatus>,
private val currencies: NonEmptyList<CryptoCurrencyStatus>,
private val isAnyTokenLoading: Boolean,
) {

View file

@ -16,12 +16,12 @@ internal class TokenListOperations(
private val currenciesRepository: CurrenciesRepository,
private val networksRepository: NetworksRepository,
private val userWalletId: UserWalletId,
private val tokens: Set<CryptoCurrencyStatus>,
private val tokens: List<CryptoCurrencyStatus>,
) {
constructor(
userWalletId: UserWalletId,
tokens: Set<CryptoCurrencyStatus>,
tokens: List<CryptoCurrencyStatus>,
useCase: GetTokenListUseCase,
) : this(
currenciesRepository = useCase.currenciesRepository,
@ -42,14 +42,14 @@ internal class TokenListOperations(
}
private fun Raise<Error>.createTokenList(isGrouped: Boolean, isSortedByBalance: Boolean): TokenList {
val tokensNes = tokens.toNonEmptySetOrNull()
val nonEmptyCurrencies = tokens.toNonEmptyListOrNull()
?: return TokenList.NotInitialized
val isAnyTokenLoading = tokensNes.any { it.value is CryptoCurrencyStatus.Loading }
val fiatBalanceOperations = TokenListFiatBalanceOperations(tokensNes, isAnyTokenLoading)
val isAnyTokenLoading = nonEmptyCurrencies.any { it.value is CryptoCurrencyStatus.Loading }
val fiatBalanceOperations = TokenListFiatBalanceOperations(nonEmptyCurrencies, isAnyTokenLoading)
return createTokenList(
tokens = tokensNes,
currencies = nonEmptyCurrencies,
fiatBalance = fiatBalanceOperations.calculateFiatBalance(),
isAnyTokenLoading = isAnyTokenLoading,
isGrouped = isGrouped,
@ -58,23 +58,23 @@ internal class TokenListOperations(
}
private fun Raise<Error>.createTokenList(
tokens: NonEmptySet<CryptoCurrencyStatus>,
currencies: NonEmptyList<CryptoCurrencyStatus>,
fiatBalance: TokenList.FiatBalance,
isAnyTokenLoading: Boolean,
isGrouped: Boolean,
isSortedByBalance: Boolean,
): TokenList {
val sortingOperations = TokenListSortingOperations(
currencies = tokens,
currencies = currencies,
isAnyTokenLoading = isAnyTokenLoading,
sortByBalance = isSortedByBalance,
)
return createTokenList(tokens, sortingOperations, fiatBalance, isGrouped)
return createTokenList(currencies, sortingOperations, fiatBalance, isGrouped)
}
private fun Raise<Error>.createTokenList(
tokens: NonEmptySet<CryptoCurrencyStatus>,
tokens: NonEmptyList<CryptoCurrencyStatus>,
sortingOperations: TokenListSortingOperations,
fiatBalance: TokenList.FiatBalance,
isGrouped: Boolean,
@ -92,7 +92,7 @@ internal class TokenListOperations(
}
}
private fun Raise<Error>.getNetworks(tokensNes: NonEmptySet<CryptoCurrencyStatus>): Set<Network> {
private fun Raise<Error>.getNetworks(tokensNes: NonEmptyList<CryptoCurrencyStatus>): Set<Network> {
val networksIds = tokensNes.map { it.currency.networkId }.toNonEmptySet()
return catch(
@ -131,7 +131,7 @@ internal class TokenListOperations(
)
private fun createUnsortedUngroupedTokenList(
tokens: Set<CryptoCurrencyStatus>,
tokens: List<CryptoCurrencyStatus>,
fiatBalance: TokenList.FiatBalance,
): TokenList.Ungrouped {
return TokenList.Ungrouped(

View file

@ -1,12 +1,10 @@
package com.tangem.domain.tokens.operations
import arrow.core.Either
import arrow.core.NonEmptySet
import arrow.core.*
import arrow.core.raise.Raise
import arrow.core.raise.either
import arrow.core.raise.ensure
import arrow.core.raise.ensureNotNull
import arrow.core.toNonEmptySetOrNull
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkGroup
import com.tangem.domain.tokens.model.TokenList
@ -14,7 +12,7 @@ import com.tangem.domain.tokens.models.Network
import java.math.BigDecimal
internal class TokenListSortingOperations(
private val currencies: Set<CryptoCurrencyStatus>,
private val currencies: List<CryptoCurrencyStatus>,
private val isAnyTokenLoading: Boolean,
private val sortByBalance: Boolean,
) {
@ -25,15 +23,15 @@ internal class TokenListSortingOperations(
isAnyTokenLoading: Boolean = tokenList.totalFiatBalance is TokenList.FiatBalance.Loading,
) : this(
currencies = when (tokenList) {
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies }.toSet()
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies }
is TokenList.Ungrouped -> tokenList.currencies
is TokenList.NotInitialized -> emptySet()
is TokenList.NotInitialized -> emptyList()
},
isAnyTokenLoading = isAnyTokenLoading,
sortByBalance = sortByBalance,
)
fun getGroupedTokens(networks: Set<Network>): Either<Error, NonEmptySet<NetworkGroup>> = either {
fun getGroupedTokens(networks: Set<Network>): Either<Error, NonEmptyList<NetworkGroup>> = either {
ensure(currencies.isNotEmpty()) { Error.EmptyTokens }
val networksNes = ensureNotNull(networks.toNonEmptySetOrNull()) {
Error.EmptyNetworks
@ -46,17 +44,17 @@ internal class TokenListSortingOperations(
}
}
fun getTokens(): Either<Error, NonEmptySet<CryptoCurrencyStatus>> = either {
val tokensNes = ensureNotNull(currencies.toNonEmptySetOrNull()) {
fun getTokens(): Either<Error, NonEmptyList<CryptoCurrencyStatus>> = either {
val nonEmptyCurrencies = ensureNotNull(currencies.toNonEmptyListOrNull()) {
Error.EmptyTokens
}
if (sortByBalance) sortTokensByBalance(tokensNes) else tokensNes
if (sortByBalance) sortTokensByBalance(nonEmptyCurrencies) else nonEmptyCurrencies
}
fun getSortType(): TokenList.SortType = if (sortByBalance) TokenList.SortType.BALANCE else TokenList.SortType.NONE
private fun Raise<Error>.groupTokens(networks: NonEmptySet<Network>): NonEmptySet<NetworkGroup> {
private fun Raise<Error>.groupTokens(networks: NonEmptySet<Network>): NonEmptyList<NetworkGroup> {
val groupedTokens = currencies
.groupBy { it.currency.networkId }
.map { (networkId, tokens) ->
@ -66,22 +64,21 @@ internal class TokenListSortingOperations(
NetworkGroup(
network = network,
currencies = ensureNotNull(tokens.toNonEmptySetOrNull()) { Error.EmptyTokens },
currencies = ensureNotNull(tokens.toNonEmptyListOrNull()) { Error.EmptyTokens },
)
}
.toNonEmptySetOrNull()
.toNonEmptyListOrNull()
return ensureNotNull(groupedTokens) { Error.EmptyTokens }
}
private fun Raise<Error>.groupAndSortTokensByBalance(networks: NonEmptySet<Network>): NonEmptySet<NetworkGroup> {
private fun Raise<Error>.groupAndSortTokensByBalance(networks: NonEmptySet<Network>): NonEmptyList<NetworkGroup> {
val groupsWithSortedTokens = groupTokens(networks)
.map { group ->
val tokens = group.currencies as? NonEmptySet<CryptoCurrencyStatus>
val tokens = group.currencies as? NonEmptyList<CryptoCurrencyStatus>
?: error("Tokens can not be empty here")
group.copy(currencies = sortTokensByBalance(tokens))
}
.toNonEmptySet()
return if (isAnyTokenLoading) {
groupsWithSortedTokens
@ -90,22 +87,22 @@ internal class TokenListSortingOperations(
}
}
private fun sortTokensByBalance(tokens: NonEmptySet<CryptoCurrencyStatus>): NonEmptySet<CryptoCurrencyStatus> {
private fun sortTokensByBalance(tokens: NonEmptyList<CryptoCurrencyStatus>): NonEmptyList<CryptoCurrencyStatus> {
return if (isAnyTokenLoading) {
tokens
} else {
tokens.sortedByDescending { it.value.fiatAmount ?: BigDecimal.ZERO }
.toNonEmptySetOrNull()
.toNonEmptyListOrNull()
?: error("Tokens can not be empty here")
}
}
private fun sortGroupsByBalance(groupsWithSortedTokens: NonEmptySet<NetworkGroup>): NonEmptySet<NetworkGroup> {
private fun sortGroupsByBalance(groupsWithSortedTokens: NonEmptyList<NetworkGroup>): NonEmptyList<NetworkGroup> {
return groupsWithSortedTokens
.sortedByDescending { group ->
group.currencies.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO }
}
.toNonEmptySetOrNull()
.toNonEmptyListOrNull()
?: error("Tokens can not be empty here")
}

View file

@ -10,11 +10,11 @@ import kotlinx.coroutines.flow.Flow
interface CurrenciesRepository {
/**
* Saves the given set of cryptocurrencies, along with the preferences for grouping and sorting, for a specific
* Saves the given list of cryptocurrencies, along with the preferences for grouping and sorting, for a specific
* multi-currency user wallet.
*
* @param userWalletId The unique identifier of the user wallet.
* @param currencies The set of cryptocurrencies to be saved.
* @param currencies The list of cryptocurrencies to be saved.
* @param isGroupedByNetwork A boolean flag indicating whether the tokens should be grouped by network.
* @param isSortedByBalance A boolean flag indicating whether the tokens should be sorted by balance.
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
@ -22,7 +22,7 @@ interface CurrenciesRepository {
*/
suspend fun saveTokens(
userWalletId: UserWalletId,
currencies: Set<CryptoCurrency>,
currencies: List<CryptoCurrency>,
isGroupedByNetwork: Boolean,
isSortedByBalance: Boolean,
)
@ -38,7 +38,7 @@ interface CurrenciesRepository {
suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency
/**
* Retrieves the set of cryptocurrencies within a multi-currency wallet.
* Retrieves the list of cryptocurrencies within a multi-currency wallet.
*
* @param userWalletId The unique identifier of the user wallet.
* @param refresh A boolean flag indicating whether the data should be refreshed.
@ -46,7 +46,7 @@ interface CurrenciesRepository {
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
* ID provided.
*/
fun getMultiCurrencyWalletCurrencies(userWalletId: UserWalletId, refresh: Boolean): Flow<Set<CryptoCurrency>>
fun getMultiCurrencyWalletCurrencies(userWalletId: UserWalletId, refresh: Boolean): Flow<List<CryptoCurrency>>
/**
* Retrieves the cryptocurrency for a specific multi-currency user wallet.

View file

@ -32,7 +32,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
val result = useCase(
userWalletId = userWalletId,
sortedTokensIds = emptySet(),
sortedTokensIds = emptyList(),
isGroupedByNetwork = false,
isSortedByBalance = false,
)
@ -54,7 +54,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
val result = useCase(
userWalletId = userWalletId,
sortedTokensIds = MockTokens.tokens.map { it.networkId to it.id }.toSet(),
sortedTokensIds = MockTokens.tokens.map { it.networkId to it.id },
isGroupedByNetwork = false,
isSortedByBalance = false,
)
@ -76,7 +76,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
useCase(
userWalletId = userWalletId,
sortedTokensIds = expectedTokens.map { it.networkId to it.id }.toSet(),
sortedTokensIds = expectedTokens.map { it.networkId to it.id },
isGroupedByNetwork = expectedIsGrouped,
isSortedByBalance = expectedIsSorted,
)
@ -100,7 +100,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
useCase(
userWalletId = userWalletId,
sortedTokensIds = expectedTokens.map { it.networkId to it.id }.toSet(),
sortedTokensIds = expectedTokens.map { it.networkId to it.id },
isGroupedByNetwork = expectedIsGrouped,
isSortedByBalance = expectedIsSorted,
)
@ -124,7 +124,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
useCase(
userWalletId = userWalletId,
sortedTokensIds = expectedTokens.map { it.networkId to it.id }.toSet(),
sortedTokensIds = expectedTokens.map { it.networkId to it.id },
isGroupedByNetwork = expectedIsGrouped,
isSortedByBalance = expectedIsSorted,
)
@ -148,7 +148,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
useCase(
userWalletId = userWalletId,
sortedTokensIds = expectedTokens.map { it.networkId to it.id }.toSet(),
sortedTokensIds = expectedTokens.map { it.networkId to it.id },
isGroupedByNetwork = expectedIsGrouped,
isSortedByBalance = expectedIsSorted,
)
@ -170,7 +170,7 @@ internal class ApplyTokenListSortingUseCaseTest {
// When
val result = useCase(
userWalletId = userWalletId,
sortedTokensIds = getSortedTokens().drop(n = 3).map { it.networkId to it.id }.toSet(),
sortedTokensIds = getSortedTokens().drop(n = 3).map { it.networkId to it.id },
isGroupedByNetwork = false,
isSortedByBalance = false,
)
@ -181,7 +181,6 @@ internal class ApplyTokenListSortingUseCaseTest {
private fun getSortedTokens() = MockTokens.tokens
.sortedBy { Random.nextInt(0, MockTokens.tokens.size) }
.toSet()
private fun getUseCase(tokensRepository: MockCurrenciesRepository = getTokensRepository()) =
ApplyTokenListSortingUseCase(
@ -191,7 +190,7 @@ internal class ApplyTokenListSortingUseCaseTest {
private fun getTokensRepository(
sortTokensResult: Either<DataError, Unit> = Unit.right(),
tokens: Flow<Either<DataError, Set<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
tokens: Flow<Either<DataError, List<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
): MockCurrenciesRepository {
return MockCurrenciesRepository(sortTokensResult, MockTokens.token1.right(), tokens, emptyFlow(), emptyFlow())
}

View file

@ -225,7 +225,7 @@ internal class GetTokenListUseCaseTest {
fun `when tokens is empty then not initialized token list should be received`() = runTest {
val expectedResult = MockTokenLists.notInitializedTokenList.right()
val useCase = getUseCase(tokens = flowOf(emptySet<CryptoCurrency>().right()))
val useCase = getUseCase(tokens = flowOf(emptyList<CryptoCurrency>().right()))
// When
val result = useCase(userWalletId).first()
@ -319,7 +319,7 @@ internal class GetTokenListUseCaseTest {
}
private fun getUseCase(
tokens: Flow<Either<DataError, Set<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
tokens: Flow<Either<DataError, List<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
quotes: Flow<Either<DataError, Set<Quote>>> = flowOf(MockQuotes.quotes.right()),
networks: Either<DataError, Set<Network>> = MockNetworks.networks.right(),
statuses: Flow<Either<DataError, Set<NetworkStatus>>> = flowOf(MockNetworks.errorNetworksStatuses.right()),

View file

@ -1,7 +1,7 @@
package com.tangem.domain.tokens.mock
import arrow.core.nonEmptySetOf
import arrow.core.toNonEmptySetOrNull
import arrow.core.nonEmptyListOf
import arrow.core.toNonEmptyListOrNull
import com.tangem.domain.tokens.model.NetworkGroup
@Suppress("MemberVisibilityCanBePrivate")
@ -11,42 +11,42 @@ internal object MockNetworksGroups {
network = MockNetworks.network1,
currencies = MockTokensStates.failedTokenStates
.filter { it.currency.networkId == MockNetworks.network1.id }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
val networkGroup2 = NetworkGroup(
network = MockNetworks.network2,
currencies = MockTokensStates.failedTokenStates
.filter { it.currency.networkId == MockNetworks.network2.id }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
val networkGroup3 = NetworkGroup(
network = MockNetworks.network3,
currencies = MockTokensStates.failedTokenStates
.filter { it.currency.networkId == MockNetworks.network3.id }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
val failedNetworksGroups = nonEmptySetOf(networkGroup1, networkGroup2, networkGroup3)
val failedNetworksGroups = nonEmptyListOf(networkGroup1, networkGroup2, networkGroup3)
val loadedNetworksGroups = failedNetworksGroups.map { group ->
group.copy(
currencies = MockTokensStates.loadedTokensStates
.filter { it.currency.networkId == group.network.id }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
}.toNonEmptySet()
}
val sortedNetworksGroups = loadedNetworksGroups.map { group ->
group.copy(
currencies = group.currencies
.sortedByDescending { it.value.fiatAmount }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
}
.sortedByDescending { group ->
group.currencies.sumOf { it.value.fiatAmount!! }
}
.toNonEmptySetOrNull()!!
.toNonEmptyListOrNull()!!
}

View file

@ -1,7 +1,7 @@
package com.tangem.domain.tokens.mock
import arrow.core.NonEmptySet
import arrow.core.toNonEmptySetOrNull
import arrow.core.NonEmptyList
import arrow.core.toNonEmptyListOrNull
import com.tangem.domain.tokens.mock.MockNetworksGroups.failedNetworksGroups
import com.tangem.domain.tokens.mock.MockNetworksGroups.loadedNetworksGroups
import com.tangem.domain.tokens.mock.MockNetworksGroups.sortedNetworksGroups
@ -18,13 +18,13 @@ internal object MockTokenLists {
val notInitializedTokenList = TokenList.NotInitialized
val emptyGroupedTokenList = TokenList.GroupedByNetwork(
groups = emptySet(),
groups = emptyList(),
totalFiatBalance = TokenList.FiatBalance.Failed,
sortedBy = TokenList.SortType.NONE,
)
val emptyUngroupedTokenList = TokenList.Ungrouped(
currencies = emptySet(),
currencies = emptyList(),
totalFiatBalance = TokenList.FiatBalance.Failed,
sortedBy = TokenList.SortType.NONE,
)
@ -43,7 +43,7 @@ internal object MockTokenLists {
val loadingUngroupedTokenList = with(failedUngroupedTokenList) {
copy(
currencies = currencies.map { it.copy(value = CryptoCurrencyStatus.Loading) }.toNonEmptySetOrNull()!!,
currencies = currencies.map { it.copy(value = CryptoCurrencyStatus.Loading) }.toNonEmptyListOrNull()!!,
totalFiatBalance = TokenList.FiatBalance.Loading,
)
}
@ -55,9 +55,9 @@ internal object MockTokenLists {
group.copy(
currencies = group.currencies
.map { it.copy(value = CryptoCurrencyStatus.Loading) }
.toNonEmptySetOrNull()!!,
.toNonEmptyListOrNull()!!,
)
}.toNonEmptySetOrNull()!!,
}.toNonEmptyListOrNull()!!,
)
}
@ -84,7 +84,7 @@ internal object MockTokenLists {
sortedBy = TokenList.SortType.NONE,
totalFiatBalance = TokenList.FiatBalance.Loaded(
amount = groups
.flatMap { it.currencies as NonEmptySet<CryptoCurrencyStatus> }
.flatMap { it.currencies as NonEmptyList<CryptoCurrencyStatus> }
.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO },
isAllAmountsSummarized = true,
),
@ -95,7 +95,7 @@ internal object MockTokenLists {
get() {
val tokens = MockTokensStates.loadedTokensStates
.sortedByDescending { it.value.fiatAmount }
.toNonEmptySetOrNull()!!
.toNonEmptyListOrNull()!!
return unsortedUngroupedTokenList.copy(
currencies = tokens,

View file

@ -119,5 +119,5 @@ internal object MockTokens {
derivationPath = null,
)
val tokens = setOf(token1, token2, token3, token4, token5, token6, token7, token8, token9, token10)
val tokens = listOf(token1, token2, token3, token4, token5, token6, token7, token8, token9, token10)
}

View file

@ -1,6 +1,6 @@
package com.tangem.domain.tokens.mock
import arrow.core.nonEmptySetOf
import arrow.core.nonEmptyListOf
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkStatus
@ -57,7 +57,7 @@ internal object MockTokensStates {
value = CryptoCurrencyStatus.NoAccount,
)
val failedTokenStates = nonEmptySetOf(
val failedTokenStates = nonEmptyListOf(
tokenState1,
tokenState2,
tokenState3,
@ -86,5 +86,5 @@ internal object MockTokensStates {
hasTransactionsInProgress = false,
),
)
}.toNonEmptySet()
}
}

View file

@ -11,12 +11,12 @@ import kotlinx.coroutines.flow.map
internal class MockCurrenciesRepository(
private val sortTokensResult: Either<DataError, Unit>,
private val token: Either<DataError, CryptoCurrency>,
private val tokens: Flow<Either<DataError, Set<CryptoCurrency>>>,
private val tokens: Flow<Either<DataError, List<CryptoCurrency>>>,
private val isGrouped: Flow<Either<DataError, Boolean>>,
private val isSortedByBalance: Flow<Either<DataError, Boolean>>,
) : CurrenciesRepository {
var tokensIdsAfterSortingApply: Set<CryptoCurrency>? = null
var tokensIdsAfterSortingApply: List<CryptoCurrency>? = null
private set
var isTokensGroupedAfterSortingApply: Boolean? = null
@ -27,7 +27,7 @@ internal class MockCurrenciesRepository(
override suspend fun saveTokens(
userWalletId: UserWalletId,
currencies: Set<CryptoCurrency>,
currencies: List<CryptoCurrency>,
isGroupedByNetwork: Boolean,
isSortedByBalance: Boolean,
) {
@ -45,7 +45,7 @@ internal class MockCurrenciesRepository(
override fun getMultiCurrencyWalletCurrencies(
userWalletId: UserWalletId,
refresh: Boolean,
): Flow<Set<CryptoCurrency>> {
): Flow<List<CryptoCurrency>> {
return tokens.map { it.getOrElse { e -> throw e } }
}