Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-07 16:02:16 +04:00
parent cb6fdddcde
commit 1ed65c48cc
28 changed files with 172 additions and 266 deletions

View file

@ -28,7 +28,7 @@ internal class AccountListConverter @AssistedInject constructor(
override fun convert(value: GetWalletAccountsResponse): AccountList {
return AccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
accounts = value.accounts.map(cryptoPortfolioConverter::convert).toSet(),
totalAccounts = value.wallet.totalAccounts,
sortType = TokensSortTypeConverter.convert(value.wallet.sort),

View file

@ -87,7 +87,7 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
}
private fun createDefaultAccountDTOs(userWallet: UserWallet): List<WalletAccountDTO> {
val accounts = AccountList.empty(userWallet).accounts
val accounts = AccountList.empty(userWallet.walletId).accounts
.filterIsInstance<Account.CryptoPortfolio>()
val converter = cryptoPortfolioCF.create(userWallet = userWallet)

View file

@ -5,6 +5,7 @@ import arrow.core.some
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.producer.MultiAccountListProducer
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -35,10 +36,11 @@ internal class DefaultMultiAccountListProducer @AssistedInject constructor(
@OptIn(ExperimentalCoroutinesApi::class)
override fun produce(): Flow<List<AccountList>> {
return userWalletsStore.userWallets
.map { it.map(UserWallet::walletId) }
.distinctUntilChanged()
.flatMapLatest { userWallets ->
.flatMapLatest { ids ->
combine(
flows = userWallets.map(walletAccountListFlowFactory::create),
flows = ids.map(walletAccountListFlowFactory::create),
transform = ::listOf,
)
}

View file

@ -2,7 +2,6 @@ package com.tangem.data.account.producer
import arrow.core.Option
import arrow.core.none
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.producer.SingleAccountListProducer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -11,16 +10,13 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapNotNull
/**
* Default implementation of [SingleAccountListProducer].
* Produces a list of [AccountList] for a specific user wallet.
*
* @property params params containing the user wallet ID
* @property userWalletsStore store that provides user wallets
* @property walletAccountListFlowFactory builder to create flows of [AccountList] for each wallet
* @property dispatchers coroutine dispatchers provider
*
@ -28,7 +24,6 @@ import kotlinx.coroutines.flow.mapNotNull
*/
internal class DefaultSingleAccountListProducer @AssistedInject constructor(
@Assisted val params: SingleAccountListProducer.Params,
private val userWalletsStore: UserWalletsStore,
private val walletAccountListFlowFactory: WalletAccountListFlowFactory,
private val dispatchers: CoroutineDispatcherProvider,
) : SingleAccountListProducer {
@ -37,11 +32,7 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
@OptIn(ExperimentalCoroutinesApi::class)
override fun produce(): Flow<AccountList> {
return userWalletsStore.userWallets
.mapNotNull { userWallets ->
userWallets.firstOrNull { it.walletId == params.userWalletId }
}
.flatMapLatest(walletAccountListFlowFactory::create)
return walletAccountListFlowFactory.create(userWalletId = params.userWalletId)
.flowOn(dispatchers.default)
}

View file

@ -4,9 +4,11 @@ import com.tangem.data.account.converter.AccountListConverter
import com.tangem.data.account.store.AccountsResponseStore
import com.tangem.data.account.store.AccountsResponseStoreFactory
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.models.wallet.requireColdWallet
import kotlinx.coroutines.flow.*
@ -22,12 +24,15 @@ import javax.inject.Inject
[REDACTED_AUTHOR]
*/
internal class WalletAccountListFlowFactory @Inject constructor(
private val userWalletsStore: UserWalletsStore,
private val accountsResponseStoreFactory: AccountsResponseStoreFactory,
private val accountListConverterFactory: AccountListConverter.Factory,
private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
) {
fun create(userWallet: UserWallet): Flow<AccountList> {
fun create(userWalletId: UserWalletId): Flow<AccountList> {
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
return if (userWallet.isMultiCurrency) {
createForMultiWallet(userWallet)
} else {
@ -53,6 +58,6 @@ internal class WalletAccountListFlowFactory @Inject constructor(
setOf(cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet = userWallet))
}
return AccountList.empty(userWallet = userWallet, cryptoCurrencies = currencies)
return AccountList.empty(userWalletId = userWallet.walletId, cryptoCurrencies = currencies)
}
}

View file

@ -101,12 +101,12 @@ internal class DefaultAccountsCRUDRepository(
}
override suspend fun saveAccounts(accountList: AccountList) {
val userWalletId = accountList.userWallet.walletId
val userWallet = userWalletsStore.getSyncStrict(accountList.userWalletId)
val converter = convertersContainer.getWalletAccountsResponseCF.create(userWallet = accountList.userWallet)
val converter = convertersContainer.getWalletAccountsResponseCF.create(userWallet = userWallet)
val accountsResponse = converter.convert(value = accountList)
walletAccountsSaver.pushAndStore(userWalletId = userWalletId, response = accountsResponse)
walletAccountsSaver.pushAndStore(userWalletId = userWallet.walletId, response = accountsResponse)
}
override suspend fun getTotalAccountsCountSync(userWalletId: UserWalletId): Option<Int> = option {

View file

@ -8,7 +8,6 @@ import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
internal fun createWalletAccountDTO(
@ -72,13 +71,13 @@ internal fun createGetWalletAccountsResponse(
}
internal fun createAccountList(
userWallet: UserWallet,
userWalletId: UserWalletId,
sortType: TokensSortType = TokensSortType.BALANCE,
groupType: TokensGroupType = TokensGroupType.NETWORK,
): AccountList {
return AccountList(
userWallet = userWallet,
accounts = setOf(createCryptoPortfolio(userWallet.walletId)),
userWalletId = userWalletId,
accounts = setOf(createCryptoPortfolio(userWalletId)),
totalAccounts = 1,
sortType = sortType,
groupType = groupType,

View file

@ -96,7 +96,7 @@ class AccountListConverterTest {
),
expected = Result.success(
createAccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
sortType = TokensSortType.BALANCE,
groupType = TokensGroupType.NETWORK,
),
@ -110,7 +110,7 @@ class AccountListConverterTest {
),
expected = Result.success(
createAccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),
@ -124,7 +124,7 @@ class AccountListConverterTest {
),
expected = Result.success(
createAccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),

View file

@ -46,7 +46,7 @@ class GetWalletAccountsResponseConverterTest {
@Test
fun `cryptoPortfolioConverter throws exception`() {
// Arrange
val domain = createAccountList(userWallet = userWallet)
val domain = createAccountList(userWalletId = userWallet.walletId)
val exception = IllegalStateException("Test exception")
every { cryptoPortfolioConverter.convertBack(any()) } throws exception
@ -92,7 +92,7 @@ class GetWalletAccountsResponseConverterTest {
return listOf(
ConvertModel(
value = createAccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
sortType = TokensSortType.BALANCE,
groupType = TokensGroupType.NETWORK,
),
@ -106,7 +106,7 @@ class GetWalletAccountsResponseConverterTest {
),
ConvertModel(
value = createAccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),

View file

@ -6,10 +6,7 @@ import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@ -19,13 +16,11 @@ class SaveWalletAccountsResponseConverterTest {
@Test
fun convert() {
// Arrange
val userWallet = mockk<UserWallet> {
every { this@mockk.walletId } returns UserWalletId("011")
}
val userWalletId = UserWalletId("011")
val accountList = AccountList(
userWallet = userWallet,
accounts = setOf(Account.CryptoPortfolio.createMainAccount(userWalletId = userWallet.walletId)),
userWalletId = userWalletId,
accounts = setOf(Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)),
totalAccounts = 1,
)
.getOrNull()!!

View file

@ -160,7 +160,7 @@ class FetchWalletAccountsErrorHandlerTest {
// Arrange
val error = ApiResponseError.TimeoutException()
val accounts = AccountList.empty(userWallet).accounts
val accounts = AccountList.empty(userWalletId).accounts
.filterIsInstance<Account.CryptoPortfolio>()
val accountDTO = WalletAccountDTO(

View file

@ -51,8 +51,8 @@ class DefaultMultiAccountListProducerTest {
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
every { walletAccountListFlowFactory.create(userWallet) } returns flowOf(accountList)
val accountList = AccountList.empty(userWalletId)
every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList)
// Act
val actual = producer.produce().let(::getEmittedValues)
@ -63,7 +63,7 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@ -73,11 +73,11 @@ class DefaultMultiAccountListProducerTest {
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
val updatedAccountList = AccountList.empty(userWallet = userWallet, sortType = TokensSortType.NONE)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = AccountList.empty(userWalletId = userWalletId, sortType = TokensSortType.NONE)
val factoryFlow = MutableStateFlow<AccountList?>(null)
every { walletAccountListFlowFactory.create(userWallet) } returns factoryFlow.filterNotNull()
every { walletAccountListFlowFactory.create(userWalletId) } returns factoryFlow.filterNotNull()
// Act (first emission)
factoryFlow.value = accountList
@ -95,9 +95,9 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@ -107,10 +107,10 @@ class DefaultMultiAccountListProducerTest {
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val factoryFlow = MutableStateFlow<AccountList?>(null)
every { walletAccountListFlowFactory.create(userWallet) } returns factoryFlow.filterNotNull()
every { walletAccountListFlowFactory.create(userWalletId) } returns factoryFlow.filterNotNull()
// Act (first emission)
factoryFlow.value = accountList
@ -128,9 +128,9 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@ -141,7 +141,7 @@ class DefaultMultiAccountListProducerTest {
every { userWalletsStore.userWallets } returns userWalletsFlow
val exception = RuntimeException("Converter error")
every { walletAccountListFlowFactory.create(userWallet) } throws exception
every { walletAccountListFlowFactory.create(userWalletId) } throws exception
// Act
val actual = producer.produceWithFallback().let(::getEmittedValues)
@ -152,7 +152,7 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@ -178,7 +178,7 @@ class DefaultMultiAccountListProducerTest {
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
every { walletAccountListFlowFactory.create(userWallet) } returns emptyFlow()
every { walletAccountListFlowFactory.create(userWalletId) } returns emptyFlow()
// Act
val actual = producer.produce().let(::getEmittedValues)
@ -188,7 +188,7 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@ -203,9 +203,9 @@ class DefaultMultiAccountListProducerTest {
val userWalletsFlow = MutableStateFlow(listOf(userWallet, userWallet2))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
every { walletAccountListFlowFactory.create(userWallet) } returns flowOf(accountList)
every { walletAccountListFlowFactory.create(userWallet2) } returns emptyFlow()
val accountList = AccountList.empty(userWalletId)
every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList)
every { walletAccountListFlowFactory.create(userWalletId2) } returns emptyFlow()
// Act
val actual = producer.produce().let(::getEmittedValues)
@ -215,8 +215,8 @@ class DefaultMultiAccountListProducerTest {
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWallet2)
walletAccountListFlowFactory.create(userWalletId)
walletAccountListFlowFactory.create(userWalletId2)
}
}
}

View file

@ -2,7 +2,6 @@ package com.tangem.data.account.producer
import com.google.common.truth.Truth
import com.tangem.common.test.utils.getEmittedValues
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.producer.SingleAccountListProducer
import com.tangem.domain.models.TokensSortType
@ -11,7 +10,6 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
@ -26,7 +24,6 @@ import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class DefaultSingleAccountListProducerTest {
private val userWalletsStore: UserWalletsStore = mockk()
private val walletAccountListFlowFactory: WalletAccountListFlowFactory = mockk()
private val userWalletId = UserWalletId("011")
@ -36,24 +33,22 @@ class DefaultSingleAccountListProducerTest {
private val producer = DefaultSingleAccountListProducer(
params = SingleAccountListProducer.Params(userWalletId = userWalletId),
userWalletsStore = userWalletsStore,
walletAccountListFlowFactory = walletAccountListFlowFactory,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@AfterEach
fun tearDownEach() {
clearMocks(userWalletsStore, walletAccountListFlowFactory)
clearMocks(walletAccountListFlowFactory)
}
@Test
fun produce() = runTest {
// Arrange
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
MutableStateFlow(listOf(userWallet))
val accountList = AccountList.empty(userWallet)
every { walletAccountListFlowFactory.create(userWallet) } returns flowOf(accountList)
val accountList = AccountList.empty(userWalletId)
every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList)
// Act
val actual = producer.produce().let(::getEmittedValues)
@ -63,22 +58,18 @@ class DefaultSingleAccountListProducerTest {
Truth.assertThat(actual).containsExactly(expected)
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
}
}
@Test
fun `flow will updated if factoryFlow is updated`() = runTest {
// Arrange
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
val updatedAccountList = AccountList.empty(userWallet = userWallet, sortType = TokensSortType.NONE)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = AccountList.empty(userWalletId = userWalletId, sortType = TokensSortType.NONE)
val factoryFlow = MutableStateFlow<AccountList?>(null)
every { walletAccountListFlowFactory.create(userWallet) } returns factoryFlow.filterNotNull()
every { walletAccountListFlowFactory.create(userWalletId) } returns factoryFlow.filterNotNull()
// Act (first emission)
factoryFlow.value = accountList
@ -95,23 +86,18 @@ class DefaultSingleAccountListProducerTest {
Truth.assertThat(secondEmission).containsExactly(updatedAccountList)
coVerifyOrder {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
walletAccountListFlowFactory.create(userWalletId)
}
}
@Test
fun `flow is filtered the same response`() = runTest {
// Arrange
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val factoryFlow = MutableStateFlow<AccountList?>(null)
every { walletAccountListFlowFactory.create(userWallet) } returns factoryFlow.filterNotNull()
every { walletAccountListFlowFactory.create(userWalletId) } returns factoryFlow.filterNotNull()
// Act (first emission)
factoryFlow.value = accountList
@ -128,71 +114,8 @@ class DefaultSingleAccountListProducerTest {
Truth.assertThat(secondEmission).containsExactly(accountList)
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
walletAccountListFlowFactory.create(userWalletId)
walletAccountListFlowFactory.create(userWalletId)
}
}
@Test
fun `flow is empty if factory throws exception`() = runTest {
// Arrange
val userWalletsFlow = MutableStateFlow(value = listOf(userWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
val exception = RuntimeException("Converter error")
every { walletAccountListFlowFactory.create(userWallet) } throws exception
// Act
val actual = producer.produceWithFallback().let(::getEmittedValues)
// Assert
Truth.assertThat(actual).isEmpty() // no emissions
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
walletAccountListFlowFactory.create(userWallet)
}
}
@Test
fun `flow is empty if userWalletsFlow returns empty flow`() = runTest {
// Arrange
val userWalletsFlow = emptyFlow<List<UserWallet>>()
every { userWalletsStore.userWallets } returns userWalletsFlow
// Act
val actual = producer.produce().let(::getEmittedValues)
// Assert
Truth.assertThat(actual).isEmpty() // no emissions
coVerify(exactly = 1) { userWalletsStore.userWallets }
coVerify(inverse = true) { walletAccountListFlowFactory.create(any()) }
}
@Test
fun `flow is empty if userWalletsFlow doesn't contains userWalletId from params`() = runTest {
// Arrange
val unknownId = UserWalletId("012")
val unknownWallet = mockk<UserWallet> {
every { this@mockk.walletId } returns unknownId
}
val userWalletsFlow = MutableStateFlow(listOf(unknownWallet))
every { userWalletsStore.userWallets } returns userWalletsFlow
// Act
val actual = producer.produce().let(::getEmittedValues)
// Assert
Truth.assertThat(actual).isEmpty() // no emissions
coVerify(ordering = Ordering.SEQUENCE) {
userWalletsStore.userWallets
}
coVerify(inverse = true) { walletAccountListFlowFactory.create(any()) }
}
}

View file

@ -10,6 +10,7 @@ import com.tangem.data.account.store.AccountsResponseStore
import com.tangem.data.account.store.AccountsResponseStoreFactory
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -28,6 +29,7 @@ import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class WalletAccountListFlowFactoryTest {
private val userWalletsStore: UserWalletsStore = mockk()
private val accountsResponseStoreFactory: AccountsResponseStoreFactory = mockk()
private val accountsResponseStore: AccountsResponseStore = mockk()
private val accountsResponseStoreFlow = MutableStateFlow<GetWalletAccountsResponse?>(value = null)
@ -38,6 +40,7 @@ class WalletAccountListFlowFactoryTest {
private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory = mockk()
private val factory = WalletAccountListFlowFactory(
userWalletsStore = userWalletsStore,
accountsResponseStoreFactory = accountsResponseStoreFactory,
accountListConverterFactory = accountListConverterFactory,
cardCryptoCurrencyFactory = cardCryptoCurrencyFactory,
@ -49,6 +52,7 @@ class WalletAccountListFlowFactoryTest {
@AfterEach
fun tearDownEach() {
clearMocks(
userWalletsStore,
accountsResponseStoreFactory,
accountsResponseStore,
accountListConverterFactory,
@ -66,17 +70,19 @@ class WalletAccountListFlowFactoryTest {
every { this@mockk.isMultiCurrency } returns true
}
every { userWalletsStore.getSyncStrict(userWalletId) } returns userWallet
val accountsResponse = createGetWalletAccountsResponse(userWalletId)
every { accountsResponseStoreFactory.create(userWalletId) } returns accountsResponseStore
every { accountsResponseStore.data } returns accountsResponseStoreFlow
accountsResponseStoreFlow.value = accountsResponse
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
every { accountListConverterFactory.create(userWallet) } returns accountListConverter
every { accountListConverter.convert(accountsResponse) } returns accountList
// Act
val actual = factory.create(userWallet).let(::getEmittedValues)
val actual = factory.create(userWalletId).let(::getEmittedValues)
// Assert
val expected = accountList
@ -99,14 +105,16 @@ class WalletAccountListFlowFactoryTest {
fun `create for single wallet`() = runTest {
val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false)
every { userWalletsStore.getSyncStrict(userWallet.walletId) } returns userWallet
val currency = cryptoCurrencyFactory.ethereum
every { cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet) } returns currency
// Act
val actual = factory.create(userWallet).let(::getEmittedValues)
val actual = factory.create(userWallet.walletId).let(::getEmittedValues)
// Assert
val expected = AccountList.empty(userWallet = userWallet, cryptoCurrencies = setOf(currency))
val expected = AccountList.empty(userWalletId = userWallet.walletId, cryptoCurrencies = setOf(currency))
Truth.assertThat(actual).containsExactly(expected)
coVerify(ordering = Ordering.SEQUENCE) {
@ -126,16 +134,18 @@ class WalletAccountListFlowFactoryTest {
fun `flow is created for single wallet with token`() = runTest {
val nodl = MockUserWalletFactory.createSingleWalletWithToken()
every { userWalletsStore.getSyncStrict(nodl.walletId) } returns nodl
val currencies = cryptoCurrencyFactory.ethereumAndStellar.toSet()
every {
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = nodl)
} returns currencies.toList()
// Act
val actual = factory.create(nodl).let(::getEmittedValues)
val actual = factory.create(nodl.walletId).let(::getEmittedValues)
// Assert
val expected = AccountList.empty(userWallet = nodl, cryptoCurrencies = currencies)
val expected = AccountList.empty(userWalletId = nodl.walletId, cryptoCurrencies = currencies)
Truth.assertThat(actual).containsExactly(expected)
coVerify(ordering = Ordering.SEQUENCE) {

View file

@ -584,7 +584,7 @@ class DefaultAccountsCRUDRepositoryTest {
every { this@mockk.walletId } returns userWalletId
}
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountsResponse = mockk<GetWalletAccountsResponse>()
accountsResponseStoreFlow.value = accountsResponse
@ -593,6 +593,8 @@ class DefaultAccountsCRUDRepositoryTest {
every { this@mockk.convert(accountList) } returns accountsResponse
}
every { userWalletsStore.getSyncStrict(userWalletId) } returns userWallet
every {
convertersContainer.getWalletAccountsResponseCF.create(userWallet = userWallet)
} returns converter
@ -617,7 +619,7 @@ class DefaultAccountsCRUDRepositoryTest {
every { this@mockk.walletId } returns userWalletId
}
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountsResponse = mockk<GetWalletAccountsResponse>()
accountsResponseStoreFlow.value = accountsResponse
@ -626,6 +628,8 @@ class DefaultAccountsCRUDRepositoryTest {
every { this@mockk.convert(accountList) } returns accountsResponse
}
every { userWalletsStore.getSyncStrict(userWalletId) } returns userWallet
every {
convertersContainer.getWalletAccountsResponseCF.create(userWallet = userWallet)
} returns converter

View file

@ -8,14 +8,14 @@ import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.extensions.addOrReplace
import kotlinx.serialization.Serializable
/**
* Represents a list of accounts associated with a user wallet
*
* @property userWallet the user wallet associated with the account list
* @property userWalletId the user wallet id associated with the account list
* @property accounts a set of accounts belonging to the user wallet
* @property totalAccounts the total number of accounts
*
@ -23,7 +23,7 @@ import kotlinx.serialization.Serializable
*/
@Serializable
data class AccountList private constructor(
val userWallet: UserWallet,
val userWalletId: UserWalletId,
val accounts: Set<Account>,
val totalAccounts: Int,
val sortType: TokensSortType,
@ -51,7 +51,7 @@ data class AccountList private constructor(
val accounts = this.accounts.addOrReplace(other) { it.accountId == other.accountId }
return invoke(
userWallet = this.userWallet,
userWalletId = this.userWalletId,
accounts = accounts,
totalAccounts = this.totalAccounts + if (isNewAccount) 1 else 0,
sortType = this.sortType,
@ -73,7 +73,7 @@ data class AccountList private constructor(
}
return invoke(
userWallet = this.userWallet,
userWalletId = this.userWalletId,
accounts = accounts,
totalAccounts = this.totalAccounts - if (isExistingAccount) 1 else 0,
sortType = this.sortType,
@ -134,12 +134,12 @@ data class AccountList private constructor(
* Factory method to create an `AccountList` instance.
* Validates the input to ensure the accounts list is not empty and contains exactly one main account.
*
* @param userWallet the user wallet associated with the account list
* @param userWalletId the user wallet id associated with the account list
* @param accounts a set of accounts belonging to the user wallet
* @param totalAccounts the total number of accounts
*/
operator fun invoke(
userWallet: UserWallet,
userWalletId: UserWalletId,
accounts: Set<Account>,
totalAccounts: Int,
sortType: TokensSortType = TokensSortType.NONE,
@ -169,7 +169,7 @@ data class AccountList private constructor(
}
AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = accounts,
totalAccounts = totalAccounts,
sortType = sortType,
@ -180,19 +180,19 @@ data class AccountList private constructor(
/**
* Factory method to create an empty [AccountList] with a main crypto portfolio account
*
* @param userWallet the user wallet associated with the account list
* @param userWalletId the user wallet id associated with the account list
*/
fun empty(
userWallet: UserWallet,
userWalletId: UserWalletId,
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
sortType: TokensSortType = TokensSortType.NONE,
groupType: TokensGroupType = TokensGroupType.NONE,
): AccountList {
return AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(
Account.CryptoPortfolio.createMainAccount(
userWalletId = userWallet.walletId,
userWalletId = userWalletId,
cryptoCurrencies = cryptoCurrencies,
),
),

View file

@ -3,13 +3,13 @@ package com.tangem.domain.account.models
import com.tangem.domain.models.TotalFiatBalance
import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.serialization.Serializable
/**
* Represents a list of account statuses associated with a user wallet
*
* @property userWallet the user wallet to which the account statuses belong
* @property userWalletId the user wallet id to which the account statuses belong
* @property accountStatuses a set of account statuses associated with the user wallet
* @property totalAccounts the total number of accounts (including archived ones)
* @property totalFiatBalance the total fiat balance across all accounts
@ -18,7 +18,7 @@ import kotlinx.serialization.Serializable
*/
@Serializable
data class AccountStatusList(
val userWallet: UserWallet,
val userWalletId: UserWalletId,
val accountStatuses: Set<AccountStatus>,
val totalAccounts: Int,
val totalFiatBalance: TotalFiatBalance,

View file

@ -8,11 +8,7 @@ import com.tangem.domain.account.utils.createAccounts
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.clearMocks
import io.mockk.mockk
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@ -31,7 +27,7 @@ class AccountListTest {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)
val accountList = AccountList(
userWallet = mockk(),
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
)
@ -49,13 +45,13 @@ class AccountListTest {
fun canAddMoreAccounts() {
// Arrange
val accountList = AccountList(
userWallet = mockk(),
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 2),
totalAccounts = 2,
).getOrNull()!!
val fullAccountList = AccountList(
userWallet = mockk(),
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
@ -67,16 +63,13 @@ class AccountListTest {
@Test
fun empty() {
// Arrange
val userWallet = mockk<UserWallet>(relaxed = true)
// Act
val actual = AccountList.empty(userWallet)
val actual = AccountList.empty(userWalletId)
// Assert
val expected = AccountList(
userWallet = userWallet,
accounts = setOf(Account.CryptoPortfolio.createMainAccount(userWalletId = userWallet.walletId)),
userWalletId = userWalletId,
accounts = setOf(Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)),
totalAccounts = 1,
).getOrNull()!!
@ -87,19 +80,12 @@ class AccountListTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Create {
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(userWallet)
}
@ParameterizedTest
@MethodSource("provideTestModels")
fun invoke(model: CreateTestModel) {
// Act
val actual = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = model.accounts,
totalAccounts = model.accounts.size,
)
@ -131,13 +117,13 @@ class AccountListTest {
createAccounts(userWalletId = userWalletId, count = 1).let {
CreateTestModel(
accounts = it,
expected = AccountList(userWallet = userWallet, accounts = it, totalAccounts = 1),
expected = AccountList(userWalletId = userWalletId, accounts = it, totalAccounts = 1),
)
},
createAccounts(userWalletId = userWalletId, count = 20).let {
CreateTestModel(
accounts = it,
expected = AccountList(userWallet = userWallet, accounts = it, totalAccounts = 20),
expected = AccountList(userWalletId = userWalletId, accounts = it, totalAccounts = 20),
)
},
CreateTestModel(
@ -171,8 +157,6 @@ class AccountListTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Plus {
private val userWallet = mockk<UserWallet>()
@ParameterizedTest
@MethodSource("provideTestModels")
fun invoke(model: PlusTestModel) {
@ -191,13 +175,13 @@ class AccountListTest {
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toAdd = newAccount,
expected = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount, newAccount),
totalAccounts = 2,
),
@ -211,13 +195,13 @@ class AccountListTest {
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toAdd = newAccount,
expected = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(newAccount),
totalAccounts = 1,
),
@ -226,7 +210,7 @@ class AccountListTest {
// endregion
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!,
@ -246,8 +230,6 @@ class AccountListTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Minus {
private val userWallet = mockk<UserWallet>()
@ParameterizedTest
@MethodSource("provideTestModels")
fun invoke(model: MinusTestModel) {
@ -266,13 +248,13 @@ class AccountListTest {
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount, secondaryAccount),
totalAccounts = 2,
).getOrNull()!!,
toRemove = secondaryAccount,
expected = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
),
@ -286,13 +268,13 @@ class AccountListTest {
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toRemove = notInList,
expected = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
),
@ -305,7 +287,7 @@ class AccountListTest {
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
@ -321,7 +303,7 @@ class AccountListTest {
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = setOf(mainAccount, secondaryAccount),
totalAccounts = 2,
).getOrNull()!!,

View file

@ -14,7 +14,6 @@ import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.account.utils.createAccounts
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.*
import kotlinx.coroutines.test.runTest
@ -35,20 +34,16 @@ class AddCryptoPortfolioUseCaseTest {
mainAccountTokensMigration = mainAccountTokensMigration,
)
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository, singleAccountListFetcher, mainAccountTokensMigration, userWallet)
every { userWallet.walletId } returns userWalletId
clearMocks(crudRepository, singleAccountListFetcher, mainAccountTokensMigration)
}
@Test
fun `invoke should add new crypto portfolio account to existing list`() = runTest {
// Arrange
val newAccount = createNewAccount()
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!!
coEvery {
@ -152,7 +147,7 @@ class AddCryptoPortfolioUseCaseTest {
fun `invoke should return error if account list requirements not met`() = runTest {
// Arrange
val accountList = AccountList(
userWallet = userWallet,
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
@ -228,7 +223,7 @@ class AddCryptoPortfolioUseCaseTest {
fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange
val newAccount = createNewAccount()
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!!
val exception = IllegalStateException("Test error")
@ -266,7 +261,7 @@ class AddCryptoPortfolioUseCaseTest {
fun `invoke should return new account if migrate returns error`() = runTest {
// Arrange
val newAccount = createNewAccount()
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!!
val exception = Exception("Migration error")

View file

@ -11,7 +11,6 @@ import com.tangem.domain.account.usecase.ArchiveCryptoPortfolioUseCase.Error
import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.*
import kotlinx.coroutines.test.runTest
@ -24,19 +23,17 @@ class ArchiveCryptoPortfolioUseCaseTest {
private val crudRepository: AccountsCRUDRepository = mockk(relaxUnitFun = true)
private val useCase = ArchiveCryptoPortfolioUseCase(crudRepository)
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository, userWallet)
every { userWallet.walletId } returns userWalletId
clearMocks(crudRepository)
}
@Test
fun `invoke should archive existing crypto portfolio account`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = (AccountList.empty(userWallet) + account).getOrNull()!!
val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!!
val accountId = account.accountId
val updatedAccountList = (accountList - account).getOrNull()!!
@ -103,7 +100,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
@Test
fun `invoke should return error if account not found`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val accountId = AccountId.forCryptoPortfolio(
userWalletId = userWalletId,
derivationIndex = DerivationIndex(1).getOrNull()!!,
@ -126,7 +123,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = (AccountList.empty(userWallet) + account).getOrNull()!!
val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!!
val accountId = account.accountId
val updatedAccountList = (accountList - account).getOrNull()!!

View file

@ -12,7 +12,6 @@ import com.tangem.domain.account.usecase.RecoverCryptoPortfolioUseCase.Error
import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.*
import kotlinx.coroutines.test.runTest
@ -28,19 +27,17 @@ class RecoverCryptoPortfolioUseCaseTest {
private val crudRepository: AccountsCRUDRepository = mockk(relaxUnitFun = true)
private val useCase = RecoverCryptoPortfolioUseCase(crudRepository)
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository, userWallet)
every { userWallet.walletId } returns userWalletId
clearMocks(crudRepository)
}
@Test
fun `invoke should recover archived crypto portfolio account`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val archivedAccount = ArchivedAccount(
accountId = account.accountId,
name = account.accountName,
@ -122,7 +119,7 @@ class RecoverCryptoPortfolioUseCaseTest {
fun `invoke should return error if getArchivedAccount throws exception`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val exception = IllegalStateException("Test error")
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
@ -146,7 +143,7 @@ class RecoverCryptoPortfolioUseCaseTest {
fun `invoke should return error if getArchivedAccount returns null`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
coEvery { crudRepository.getArchivedAccountSync(account.accountId) } returns None
@ -169,7 +166,7 @@ class RecoverCryptoPortfolioUseCaseTest {
fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange
val account = createAccount(userWalletId)
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val archivedAccount = ArchivedAccount(
accountId = account.accountId,
name = account.accountName,

View file

@ -12,7 +12,6 @@ import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.*
import kotlinx.coroutines.test.runTest
@ -29,19 +28,15 @@ class UpdateCryptoPortfolioUseCaseTest {
private val crudRepository: AccountsCRUDRepository = mockk(relaxUnitFun = true)
private val useCase = UpdateCryptoPortfolioUseCase(crudRepository = crudRepository)
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository, userWallet)
every { userWallet.walletId } returns userWalletId
clearMocks(crudRepository)
}
@Test
fun `invoke should update crypto portfolio account with new name`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
@ -66,7 +61,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke should update crypto portfolio account with new icon`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
val newAccountIcon = CryptoPortfolioIcon.ofCustomAccount(
@ -94,7 +89,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke should update crypto portfolio account with new name and icon`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
@ -123,7 +118,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if name and icon are null`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
@ -144,7 +139,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if getAccounts throws exception`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
@ -192,7 +187,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if getAccounts does not contain accountId`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = AccountId.forCryptoPortfolio(
userWalletId = userWalletId,
derivationIndex = DerivationIndex(1).getOrNull()!!,
@ -217,7 +212,7 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if saveAccounts throws exception`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet = userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!

View file

@ -6,6 +6,7 @@ import com.tangem.domain.account.models.AccountStatusList
import com.tangem.domain.account.producer.SingleAccountListProducer
import com.tangem.domain.account.status.utils.CryptoCurrencyStatusesFlowFactory
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.core.utils.lceContent
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.TokensGroupType
@ -39,6 +40,7 @@ import java.math.BigDecimal
@OptIn(ExperimentalCoroutinesApi::class)
internal class DefaultSingleAccountStatusListProducer @AssistedInject constructor(
@Assisted private val params: SingleAccountStatusListProducer.Params,
private val userWalletsListRepository: UserWalletsListRepository,
private val singleAccountListSupplier: SingleAccountListSupplier,
private val cryptoCurrencyStatusesFlowFactory: CryptoCurrencyStatusesFlowFactory,
private val dispatchers: CoroutineDispatcherProvider,
@ -58,8 +60,12 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
if (account.cryptoCurrencies.isEmpty()) {
createEmptyAccountStatusFlow(account)
} else {
val userWallet = userWalletsListRepository.userWalletsSync().first {
it.walletId == params.userWalletId
}
getAccountStatusFlow(
userWallet = accountList.userWallet,
userWallet = userWallet,
account = account,
groupType = accountList.groupType,
sortType = accountList.sortType,
@ -71,7 +77,7 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
val balances = accountStatuses.map { it.tokenList.totalFiatBalance }
AccountStatusList(
userWallet = accountList.userWallet,
userWalletId = accountList.userWalletId,
accountStatuses = accountStatuses.toSet(),
totalAccounts = accountList.totalAccounts,
totalFiatBalance = TotalFiatBalanceCalculator.calculate(balances),

View file

@ -117,7 +117,7 @@ class GetAccountCurrencyByAddressUseCase(
.firstOrNull()
return ensureNotNull(result) {
"No account found for network: $networkId in walletId: ${accountList.userWallet.walletId}"
"No account found for network: $networkId in walletId: ${accountList.userWalletId}"
}
}

View file

@ -9,6 +9,7 @@ import com.tangem.domain.account.models.AccountStatusList
import com.tangem.domain.account.producer.SingleAccountListProducer
import com.tangem.domain.account.status.utils.CryptoCurrencyStatusesFlowFactory
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.core.utils.lceContent
import com.tangem.domain.core.utils.lceLoading
import com.tangem.domain.models.StatusSource
@ -37,6 +38,7 @@ import java.math.BigDecimal
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class DefaultSingleAccountStatusListProducerTest {
private val userWalletsListRepository: UserWalletsListRepository = mockk()
private val singleAccountListSupplier: SingleAccountListSupplier = mockk()
private val cryptoCurrencyStatusesFlowFactory: CryptoCurrencyStatusesFlowFactory = mockk()
@ -47,6 +49,7 @@ class DefaultSingleAccountStatusListProducerTest {
private val producer = DefaultSingleAccountStatusListProducer(
params = SingleAccountStatusListProducer.Params(userWalletId),
userWalletsListRepository = userWalletsListRepository,
singleAccountListSupplier = singleAccountListSupplier,
cryptoCurrencyStatusesFlowFactory = cryptoCurrencyStatusesFlowFactory,
dispatchers = TestingCoroutineDispatcherProvider(),
@ -60,7 +63,7 @@ class DefaultSingleAccountStatusListProducerTest {
@Test
fun `flow is mapped for user wallet id from params`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId = userWalletId)
every {
singleAccountListSupplier(params = SingleAccountListProducer.Params(userWalletId))
@ -71,7 +74,7 @@ class DefaultSingleAccountStatusListProducerTest {
// Assert
val expected = AccountStatusList(
userWallet = userWallet,
userWalletId = userWalletId,
accountStatuses = setOf(
AccountStatus.CryptoPortfolio(
account = accountList.mainAccount,
@ -92,8 +95,8 @@ class DefaultSingleAccountStatusListProducerTest {
@Test
fun `flow will updated if balances are updated`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet)
val updatedAccountList = AccountList.empty(userWallet = userWallet, sortType = TokensSortType.BALANCE)
val accountList = AccountList.empty(userWalletId)
val updatedAccountList = AccountList.empty(userWalletId = userWalletId, sortType = TokensSortType.BALANCE)
val accountListFlow = MutableStateFlow(value = accountList)
@ -106,7 +109,7 @@ class DefaultSingleAccountStatusListProducerTest {
// Assert (first emission)
val expected = AccountStatusList(
userWallet = userWallet,
userWalletId = userWalletId,
accountStatuses = setOf(
AccountStatus.CryptoPortfolio(
account = accountList.mainAccount,
@ -125,7 +128,7 @@ class DefaultSingleAccountStatusListProducerTest {
// Assert (second emission)
val expected2 = AccountStatusList(
userWallet = userWallet,
userWalletId = userWalletId,
accountStatuses = setOf(
AccountStatus.CryptoPortfolio(
account = updatedAccountList.mainAccount,
@ -147,7 +150,7 @@ class DefaultSingleAccountStatusListProducerTest {
@Test
fun `flow is filtered the same balance`() = runTest {
// Arrange
val accountList = AccountList.empty(userWallet)
val accountList = AccountList.empty(userWalletId)
val accountListFlow = MutableStateFlow(value = accountList)
every {
@ -155,7 +158,7 @@ class DefaultSingleAccountStatusListProducerTest {
} returns accountListFlow
val expected = AccountStatusList(
userWallet = userWallet,
userWalletId = userWalletId,
accountStatuses = setOf(
AccountStatus.CryptoPortfolio(
account = accountList.mainAccount,
@ -191,10 +194,12 @@ class DefaultSingleAccountStatusListProducerTest {
// Arrange
val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
val accountList = AccountList.empty(
userWallet = userWallet,
userWalletId = userWalletId,
cryptoCurrencies = cryptoCurrencyFactory.ethereumAndStellar.toSet(),
)
coEvery { userWalletsListRepository.userWalletsSync() } returns listOf(userWallet)
every {
singleAccountListSupplier(params = SingleAccountListProducer.Params(userWalletId))
} returns flowOf(accountList)
@ -220,7 +225,7 @@ class DefaultSingleAccountStatusListProducerTest {
// Assert
val expected = AccountStatusList(
userWallet = userWallet,
userWalletId = userWalletId,
accountStatuses = setOf(
AccountStatus.CryptoPortfolio(
account = accountList.mainAccount,

View file

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

View file

@ -28,7 +28,7 @@ interface PortfolioFetcher {
val walletBalance: Lce<TokenListError, TotalFiatBalance>,
val accountsBalance: AccountStatusList,
) {
val userWallet: UserWallet get() = accountsBalance.userWallet
val userWalletId: UserWalletId get() = accountsBalance.userWalletId
}
sealed interface Mode {

View file

@ -140,7 +140,7 @@ internal class AccountsViewModel @Inject constructor(
// It's temporary solution to create main account for testing purposes
val accountList = AccountList(
userWallet = userWallet,
userWalletId = userWallet.walletId,
accounts = setOf(
Account.CryptoPortfolio.createMainAccount(userWallet.walletId).copy(
accountName = AccountName.invoke(value = "Main Account").getOrNull()!!,