Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-12 13:01:17 +05:00
parent 207dbeed3c
commit 0ae9e75e90
16 changed files with 55 additions and 60 deletions

View file

@ -37,9 +37,9 @@ internal class CryptoPortfolioConverter @AssistedInject constructor(
tokens = tokens,
userWallet = userWallet,
accountIndex = value.derivationIndex.toDerivationIndex(),
).toSet()
)
} else {
emptySet()
emptyList()
},
)
}

View file

@ -55,9 +55,9 @@ internal class WalletAccountListFlowFactory @Inject constructor(
val isSingleWalletWithToken = userWallet.requireColdWallet().cardTypesResolver.isSingleWalletWithToken()
val currencies = if (isSingleWalletWithToken) {
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = userWallet).toSet()
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = userWallet)
} else {
setOf(cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet = userWallet))
listOf(cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet = userWallet))
}
return AccountList.empty(userWalletId = userWallet.walletId, cryptoCurrencies = currencies)

View file

@ -119,7 +119,7 @@ class WalletAccountListFlowFactoryTest {
val actual = factory.create(userWallet.walletId).let(::getEmittedValues)
// Assert
val expected = AccountList.empty(userWalletId = userWallet.walletId, cryptoCurrencies = setOf(currency))
val expected = AccountList.empty(userWalletId = userWallet.walletId, cryptoCurrencies = listOf(currency))
Truth.assertThat(actual).containsExactly(expected)
coVerifySequence {
@ -144,7 +144,7 @@ class WalletAccountListFlowFactoryTest {
every { userWalletsListRepository.userWallets } returns userWalletsFlow
val currencies = cryptoCurrencyFactory.ethereumAndStellar.toSet()
val currencies = cryptoCurrencyFactory.ethereumAndStellar
every {
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = nodl)
} returns currencies.toList()

View file

@ -235,7 +235,7 @@ data class AccountList private constructor(
*/
fun empty(
userWalletId: UserWalletId,
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
cryptoCurrencies: List<CryptoCurrency> = emptyList(),
sortType: TokensSortType = TokensSortType.NONE,
groupType: TokensGroupType = TokensGroupType.NONE,
): AccountList {

View file

@ -81,7 +81,7 @@ class AddCryptoPortfolioUseCase(
accountName = accountName,
icon = icon,
derivationIndex = derivationIndex,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
}

View file

@ -14,8 +14,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.tokens.error.TokenListSortingError
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import timber.log.Timber
@ -137,7 +135,6 @@ class ApplyTokenListSortingUseCaseV2(
errors[account.accountId] = it
return@map account
}
.toSet()
account.copy(cryptoCurrencies = accountCurrencies)
}
@ -171,17 +168,13 @@ class ApplyTokenListSortingUseCaseV2(
private suspend fun Raise<TokenListSortingError>.applySorting(accountList: AccountList) {
coroutineScope {
val results = awaitAll(
async {
Either.catch { accountsCRUDRepository.saveAccountsLocally(accountList) }
},
async {
Either.catch { accountsCRUDRepository.syncTokens(accountList.userWalletId) }
},
)
val results = Either.catch {
accountsCRUDRepository.saveAccountsLocally(accountList)
accountsCRUDRepository.syncTokens(accountList.userWalletId)
}
ensure(results.none { it.isLeft() }) {
val message = results.mapNotNull { it.leftOrNull() }.joinToString()
ensure(results.isRight()) {
val message = results.leftOrNull()
raise(TokenListSortingError.DataError(IllegalStateException(message)))
}
}

View file

@ -86,7 +86,7 @@ class ManageCryptoCurrenciesUseCase(
}
saveAccount(
account = accountStatus.account.copy(cryptoCurrencies = modifiedCurrencyList.total.toSet()),
account = accountStatus.account.copy(cryptoCurrencies = modifiedCurrencyList.total),
)
derivePublicKeys(userWalletId = userWalletId, currencies = modifiedCurrencyList.added)
@ -126,7 +126,7 @@ class ManageCryptoCurrenciesUseCase(
val modifiedCurrencyList = accountStatus.tokenList.flattenCurrencies()
.modify(add = listOf(tokenToAdd))
saveAccount(account = accountStatus.account.copy(cryptoCurrencies = modifiedCurrencyList.total.toSet()))
saveAccount(account = accountStatus.account.copy(cryptoCurrencies = modifiedCurrencyList.total))
parallelUpdatingScope.launch {
syncTokens(userWalletId, modifiedCurrencyList)

View file

@ -100,7 +100,7 @@ class RecoverCryptoPortfolioUseCase(
accountName = this.name,
icon = this.icon,
derivationIndex = this.derivationIndex,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
}

View file

@ -65,7 +65,7 @@ internal class ApplyTokenListSortingUseCaseTest {
@Test
fun `when getAccountListSync throws exception then error should be received`() = runTest {
// Arrange
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptySet())
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptyList())
val exception = IllegalStateException("No internet connection")
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } throws exception
@ -92,7 +92,7 @@ internal class ApplyTokenListSortingUseCaseTest {
@Test
fun `when saveAccountsLocally throws exception then error should be received`() = runTest {
// Arrange
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptySet())
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptyList())
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
@ -114,14 +114,16 @@ internal class ApplyTokenListSortingUseCaseTest {
coVerifyOrder {
accountsCRUDRepository.getAccountListSync(userWalletId)
accountsCRUDRepository.saveAccountsLocally(accountList)
accountsCRUDRepository.syncTokens(userWalletId = userWalletId)
}
coVerifyOrder(inverse = true) {
accountsCRUDRepository.syncTokens(userWalletId = any())
}
}
@Test
fun `when syncTokens throws exception then error should be received`() = runTest {
// Arrange
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptySet())
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = emptyList())
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
@ -156,13 +158,13 @@ internal class ApplyTokenListSortingUseCaseTest {
val accountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
)
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
val sortedTokens = setOf(token2, token3, token1)
val sortedTokens = listOf(token2, token3, token1)
val updatedAccountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = sortedTokens,
@ -197,13 +199,13 @@ internal class ApplyTokenListSortingUseCaseTest {
val accountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
)
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
val sortedTokens = setOf(token2, token3, token1)
val sortedTokens = listOf(token2, token3, token1)
val updatedAccountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = sortedTokens,
@ -238,13 +240,13 @@ internal class ApplyTokenListSortingUseCaseTest {
val accountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
)
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
val sortedTokens = setOf(token2, token3, token1)
val sortedTokens = listOf(token2, token3, token1)
val updatedAccountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = sortedTokens,
@ -279,13 +281,13 @@ internal class ApplyTokenListSortingUseCaseTest {
val accountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
sortType = TokensSortType.BALANCE,
groupType = TokensGroupType.NETWORK,
)
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
val sortedTokens = setOf(token2, token3, token1)
val sortedTokens = listOf(token2, token3, token1)
val updatedAccountList = AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = sortedTokens,
@ -323,13 +325,13 @@ internal class ApplyTokenListSortingUseCaseTest {
name = "Account 1",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
)
.getOrNull()!!
val accountList = (AccountList.empty(
userWalletId = userWalletId,
cryptoCurrencies = setOf(token1, token2, token3),
cryptoCurrencies = listOf(token1, token2, token3),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
) + customAccount).getOrNull()!!
@ -344,7 +346,7 @@ internal class ApplyTokenListSortingUseCaseTest {
val updatedAccountList = AccountList(
userWalletId = userWalletId,
accounts = listOf(
accountList.mainAccount.copy(cryptoCurrencies = setOf(token3, token2, token1)),
accountList.mainAccount.copy(cryptoCurrencies = listOf(token3, token2, token1)),
customAccount, // unchanged due to error
),
totalAccounts = accountList.totalAccounts,

View file

@ -252,7 +252,7 @@ class GetAccountCurrencyByAddressUseCaseTest {
network = currency.network,
value = NetworkStatus.Unreachable(address = validNetworkAddress),
)
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = setOf(currency))
val accountList = AccountList.empty(userWalletId = userWalletId, cryptoCurrencies = listOf(currency))
every { userWalletsListRepository.userWallets.value } returns listOf(multiUserWallet)
coEvery {

View file

@ -103,7 +103,7 @@ class GetAccountCurrencyStatusUseCaseTest {
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
every { this@mockk.derivationIndex } returns DerivationIndex(1).getOrNull()!!
every { this@mockk.cryptoCurrencies } returns setOf(currency)
every { this@mockk.cryptoCurrencies } returns listOf(currency)
}
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
val accountStatus = AccountStatus.CryptoPortfolio(
@ -140,7 +140,7 @@ class GetAccountCurrencyStatusUseCaseTest {
fun `invokeSync returns Some if network is null`() = runTest {
// Arrange
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
every { this@mockk.cryptoCurrencies } returns setOf(currency)
every { this@mockk.cryptoCurrencies } returns listOf(currency)
}
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
val accountStatus = AccountStatus.CryptoPortfolio(
@ -223,7 +223,7 @@ class GetAccountCurrencyStatusUseCaseTest {
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
every { this@mockk.derivationIndex } returns DerivationIndex(1).getOrNull()!!
every { this@mockk.cryptoCurrencies } returns setOf(currency)
every { this@mockk.cryptoCurrencies } returns listOf(currency)
}
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
val accountStatus = AccountStatus.CryptoPortfolio(
@ -257,7 +257,7 @@ class GetAccountCurrencyStatusUseCaseTest {
fun `invoke returns data if network is null`() = runTest {
// Arrange
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
every { this@mockk.cryptoCurrencies } returns setOf(currency)
every { this@mockk.cryptoCurrencies } returns listOf(currency)
}
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
val accountStatus = AccountStatus.CryptoPortfolio(

View file

@ -266,7 +266,7 @@ class RecoverCryptoPortfolioUseCaseTest {
accountName = AccountName(name).getOrNull()!!,
icon = icon,
derivationIndex = derivationIndex,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
}

View file

@ -42,7 +42,7 @@ sealed interface Account {
override val accountName: AccountName,
val icon: CryptoPortfolioIcon,
val derivationIndex: DerivationIndex,
val cryptoCurrencies: Set<CryptoCurrency>,
val cryptoCurrencies: List<CryptoCurrency>,
) : Account {
/** Indicates if the account is the main account */
@ -60,7 +60,7 @@ sealed interface Account {
fun copy(
accountName: AccountName = this.accountName,
icon: CryptoPortfolioIcon = this.icon,
cryptoCurrencies: Set<CryptoCurrency> = this.cryptoCurrencies,
cryptoCurrencies: List<CryptoCurrency> = this.cryptoCurrencies,
): CryptoPortfolio {
return CryptoPortfolio(
accountId = this.accountId,
@ -102,7 +102,7 @@ sealed interface Account {
name: String,
icon: CryptoPortfolioIcon,
derivationIndex: Int,
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
cryptoCurrencies: List<CryptoCurrency> = emptyList(),
): Either<Error, CryptoPortfolio> {
return either {
val accountName = AccountName(value = name).getOrElse {
@ -138,7 +138,7 @@ sealed interface Account {
accountName: AccountName,
icon: CryptoPortfolioIcon,
derivationIndex: DerivationIndex,
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
cryptoCurrencies: List<CryptoCurrency> = emptyList(),
): CryptoPortfolio {
return CryptoPortfolio(
accountId = accountId,
@ -157,7 +157,7 @@ sealed interface Account {
*/
fun createMainAccount(
userWalletId: UserWalletId,
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
cryptoCurrencies: List<CryptoCurrency> = emptyList(),
): CryptoPortfolio {
val derivationIndex = DerivationIndex.Main

View file

@ -50,8 +50,8 @@ class AccountTest {
@Test
fun `CryptoPortfolio tokensCount`() {
// Arrange
val emptyCurrencies = emptySet<CryptoCurrency>()
val filledCurrencies = setOf(mockk<CryptoCurrency>())
val emptyCurrencies = emptyList<CryptoCurrency>()
val filledCurrencies = listOf(mockk<CryptoCurrency>())
// Act
val actual1 = createCryptoPortfolioStub(currencies = emptyCurrencies)
@ -68,8 +68,8 @@ class AccountTest {
@Test
fun `CryptoPortfolio networksCount`() {
// Arrange
val emptyCurrencies = emptySet<CryptoCurrency>()
val filledCurrencies = setOf(
val emptyCurrencies = emptyList<CryptoCurrency>()
val filledCurrencies = listOf(
mockk<CryptoCurrency> {
every { network } returns mockk()
},
@ -102,7 +102,7 @@ class AccountTest {
name = name,
icon = mockk(),
derivationIndex = 0,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
.leftOrNull()!!
@ -123,7 +123,7 @@ class AccountTest {
name = "Test Account",
icon = CryptoPortfolioIcon.ofMainAccount(userWalletId = UserWalletId("011")),
derivationIndex = derivationIndex.value,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
.getOrNull()!!
@ -150,7 +150,7 @@ class AccountTest {
accountName = AccountName.DefaultMain,
icon = CryptoPortfolioIcon.ofMainAccount(userWalletId),
derivationIndex = derivationIndex,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
Truth.assertThat(actual).isEqualTo(expected)
@ -161,7 +161,7 @@ class AccountTest {
userWalletId: UserWalletId = UserWalletId("011"),
name: String = "Test Account",
derivationIndex: Int = 0,
currencies: Set<CryptoCurrency> = emptySet(),
currencies: List<CryptoCurrency> = emptyList(),
): CryptoPortfolio {
val accountIndex = DerivationIndex(value = derivationIndex).getOrNull()!!

View file

@ -212,7 +212,7 @@ internal class TesterAccountsViewModel @Inject constructor(
name = "Account #$nextIndex",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = nextIndex,
cryptoCurrencies = emptySet(),
cryptoCurrencies = emptyList(),
)
.getOrNull()
?: break

View file

@ -46,7 +46,7 @@ object MockAccounts {
derivationIndex: Int,
name: String = "Account #$derivationIndex",
icon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
cryptoCurrencies: List<CryptoCurrency> = emptyList(),
userWalletId: UserWalletId = this.userWalletId,
): Account.CryptoPortfolio {
val derivationIndex = DerivationIndex(derivationIndex).getOrNull()!!