Updated on 2026-08-14
This commit is contained in:
parent
d3320b9e8b
commit
cde13c66d3
7 changed files with 42 additions and 35 deletions
|
|
@ -19,7 +19,7 @@ import kotlinx.serialization.Serializable
|
|||
@Serializable
|
||||
data class AccountStatusList(
|
||||
val userWalletId: UserWalletId,
|
||||
val accountStatuses: Set<AccountStatus>,
|
||||
val accountStatuses: List<AccountStatus>,
|
||||
val totalAccounts: Int,
|
||||
val totalFiatBalance: TotalFiatBalance,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import arrow.core.Option
|
|||
import arrow.core.none
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
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
|
||||
|
|
@ -31,6 +31,7 @@ import java.math.BigDecimal
|
|||
* Produces a flow of [AccountStatusList] for a single user wallet.
|
||||
*
|
||||
* @property params Parameters containing the user wallet ID.
|
||||
* @property accountsCRUDRepository Repository for accessing account data.
|
||||
* @property singleAccountListSupplier Supplier to get the list of accounts for the user wallet.
|
||||
* @property cryptoCurrencyStatusesFlowFactory Factory to create flows of cryptocurrency statuses.
|
||||
* @property dispatchers Coroutine dispatcher provider for managing threading.
|
||||
|
|
@ -40,7 +41,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 accountsCRUDRepository: AccountsCRUDRepository,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val cryptoCurrencyStatusesFlowFactory: CryptoCurrencyStatusesFlowFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -61,9 +62,11 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
if (account.cryptoCurrencies.isEmpty()) {
|
||||
createEmptyAccountStatusFlow(account)
|
||||
} else {
|
||||
val userWallet = userWalletsListRepository.userWalletsSync().first {
|
||||
it.walletId == params.userWalletId
|
||||
}
|
||||
val userWallet = accountsCRUDRepository.getUserWallets()
|
||||
.mapNotNull { wallets ->
|
||||
wallets.find { it.walletId == params.userWalletId }
|
||||
}
|
||||
.first()
|
||||
|
||||
getAccountStatusFlow(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -80,7 +83,7 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
|
||||
AccountStatusList(
|
||||
userWalletId = accountList.userWalletId,
|
||||
accountStatuses = accountStatuses.toSet(),
|
||||
accountStatuses = accountStatuses.toList(),
|
||||
totalAccounts = accountList.totalAccounts,
|
||||
totalFiatBalance = TotalFiatBalanceCalculator.calculate(balances),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -84,17 +84,24 @@ class ManageCryptoCurrenciesUseCase(
|
|||
account = account.copy(cryptoCurrencies = modifiedCurrencyList.total.toSet()),
|
||||
)
|
||||
|
||||
derivePublicKeys(userWalletId = userWalletId, currencies = modifiedCurrencyList.added)
|
||||
val isDerivingFailed = derivePublicKeys(
|
||||
userWalletId = userWalletId,
|
||||
currencies = modifiedCurrencyList.added,
|
||||
).isLeft()
|
||||
|
||||
parallelUpdatingScope.launch {
|
||||
/*
|
||||
* If only removal of currencies happened, we need to sync tokens. Otherwise, tokens will be synced
|
||||
* when balances are refreshed for added currencies.
|
||||
*/
|
||||
if (modifiedCurrencyList.added.isEmpty() && modifiedCurrencyList.removed.isNotEmpty()) {
|
||||
val isOnlyRemoval = modifiedCurrencyList.added.isEmpty() && modifiedCurrencyList.removed.isNotEmpty()
|
||||
|
||||
if (isDerivingFailed || isOnlyRemoval) {
|
||||
launch { accountsCRUDRepository.syncTokens(userWalletId) }
|
||||
}
|
||||
|
||||
if (isDerivingFailed) return@launch
|
||||
|
||||
cryptoCurrencyBalanceFetcher(userWalletId = userWalletId, currencies = modifiedCurrencyList.added)
|
||||
refreshExpress(userWalletId = userWalletId, currencies = modifiedCurrencyList.total)
|
||||
clearMetadata(userWalletId = userWalletId, currencies = modifiedCurrencyList.removed)
|
||||
|
|
@ -204,14 +211,11 @@ class ManageCryptoCurrenciesUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Throwable>.derivePublicKeys(
|
||||
private suspend fun derivePublicKeys(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
) {
|
||||
catch(
|
||||
block = { derivationsRepository.derivePublicKeys(userWalletId = userWalletId, currencies = currencies) },
|
||||
catch = ::raise,
|
||||
)
|
||||
): Either<Throwable, Unit> = Either.catch {
|
||||
derivationsRepository.derivePublicKeys(userWalletId = userWalletId, currencies = currencies)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrency>.groupByNetwork(
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ internal object AccountCryptoCurrencyStatusFinder {
|
|||
* @param network the network to filter accounts by, can be null.
|
||||
* @return a set of [AccountStatus] that match the expected criteria.
|
||||
*/
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(network: Network?): Set<AccountStatus> {
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(network: Network?): List<AccountStatus> {
|
||||
val possibleAccountIndex = network?.getAccountIndexOrNull()
|
||||
|
||||
return when (possibleAccountIndex) {
|
||||
// currency can be in any account
|
||||
null -> accountStatuses
|
||||
// currency only in the main account
|
||||
DerivationIndex.Main.value -> setOf(mainAccount)
|
||||
DerivationIndex.Main.value -> listOf(mainAccount)
|
||||
// currency only in the account with specific derivation index or in the main account
|
||||
else -> {
|
||||
val accountStatus = accountStatuses.firstOrNull {
|
||||
|
|
@ -74,7 +74,7 @@ internal object AccountCryptoCurrencyStatusFinder {
|
|||
cryptoPortfolio.derivationIndex.value == possibleAccountIndex
|
||||
}
|
||||
|
||||
setOfNotNull(accountStatus, mainAccount)
|
||||
listOfNotNull(accountStatus, mainAccount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import com.tangem.common.test.utils.getEmittedValues
|
|||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
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
|
||||
|
|
@ -38,7 +38,7 @@ import java.math.BigDecimal
|
|||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class DefaultSingleAccountStatusListProducerTest {
|
||||
|
||||
private val userWalletsListRepository: UserWalletsListRepository = mockk()
|
||||
private val accountsCRUDRepository: AccountsCRUDRepository = mockk()
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier = mockk()
|
||||
private val cryptoCurrencyStatusesFlowFactory: CryptoCurrencyStatusesFlowFactory = mockk()
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
|
||||
private val producer = DefaultSingleAccountStatusListProducer(
|
||||
params = SingleAccountStatusListProducer.Params(userWalletId),
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
accountsCRUDRepository = accountsCRUDRepository,
|
||||
singleAccountListSupplier = singleAccountListSupplier,
|
||||
cryptoCurrencyStatusesFlowFactory = cryptoCurrencyStatusesFlowFactory,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
|
|
@ -57,7 +57,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
clearMocks(singleAccountListSupplier, cryptoCurrencyStatusesFlowFactory)
|
||||
clearMocks(accountsCRUDRepository, singleAccountListSupplier, cryptoCurrencyStatusesFlowFactory)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -75,7 +75,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
// Assert
|
||||
val expected = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = setOf(
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = accountList.mainAccount,
|
||||
tokenList = TokenList.Empty,
|
||||
|
|
@ -110,7 +110,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
// Assert (first emission)
|
||||
val expected = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = setOf(
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = accountList.mainAccount,
|
||||
tokenList = TokenList.Empty,
|
||||
|
|
@ -129,7 +129,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
// Assert (second emission)
|
||||
val expected2 = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = setOf(
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = updatedAccountList.mainAccount,
|
||||
tokenList = TokenList.Empty,
|
||||
|
|
@ -159,7 +159,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
|
||||
val expected = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = setOf(
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = accountList.mainAccount,
|
||||
tokenList = TokenList.Empty,
|
||||
|
|
@ -198,7 +198,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
cryptoCurrencies = cryptoCurrencyFactory.ethereumAndStellar.toSet(),
|
||||
)
|
||||
|
||||
coEvery { userWalletsListRepository.userWalletsSync() } returns listOf(userWallet)
|
||||
coEvery { accountsCRUDRepository.getUserWallets() } returns flowOf(listOf(userWallet))
|
||||
|
||||
every {
|
||||
singleAccountListSupplier(params = SingleAccountListProducer.Params(userWalletId))
|
||||
|
|
@ -226,7 +226,7 @@ class DefaultSingleAccountStatusListProducerTest {
|
|||
// Assert
|
||||
val expected = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = setOf(
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = accountList.mainAccount,
|
||||
tokenList = TokenList.Ungrouped(
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(accountStatus)
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
|
@ -117,7 +117,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(mainAccountStatus, accountStatus, mockk())
|
||||
every { this@mockk.accountStatuses } returns listOf(mainAccountStatus, accountStatus, mockk())
|
||||
}
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
|
@ -154,7 +154,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(accountStatus)
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
|
@ -198,7 +198,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(accountStatus)
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
|
@ -237,7 +237,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(mainAccountStatus, accountStatus, mockk())
|
||||
every { this@mockk.accountStatuses } returns listOf(mainAccountStatus, accountStatus, mockk())
|
||||
}
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
|
@ -271,7 +271,7 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns setOf(accountStatus)
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ internal data class AvailableToAddData(
|
|||
|
||||
internal data class AvailableToAddWallet(
|
||||
val userWallet: UserWallet,
|
||||
val accounts: Set<AccountStatus>,
|
||||
val accounts: List<AccountStatus>,
|
||||
val availableNetworks: Set<TokenMarketInfo.Network>,
|
||||
val availableToAddAccounts: Map<AccountId, AvailableToAddAccount>,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue