Updated on 2026-08-14
This commit is contained in:
parent
24d7953389
commit
8683516c59
24 changed files with 817 additions and 148 deletions
|
|
@ -11,6 +11,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
internal fun String.toAccountId(userWalletId: UserWalletId): AccountId {
|
||||
return when {
|
||||
startsWith(AccountId.PaymentAccountIdPrefix) -> AccountId.forPaymentAccount(userWalletId).right()
|
||||
startsWith(AccountId.VirtualAccountIdPrefix) -> AccountId.forVirtualAccount(userWalletId).right()
|
||||
else -> AccountId.forCryptoPortfolio(value = this, userWalletId = userWalletId)
|
||||
}.getOrElse {
|
||||
error("Unable to create AccountId from value: $this. Cause: $it")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.domain.common.wallets.getSyncStrict
|
|||
import com.tangem.domain.core.flow.FlowProducerTools
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.features.virtualaccount.VirtualAccountFeatureToggles
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
|
@ -37,6 +38,7 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
|
|||
override val flowProducerTools: FlowProducerTools,
|
||||
private val walletAccountListFlowFactory: WalletAccountListFlowFactory,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val virtualAccountsFeatureToggles: VirtualAccountFeatureToggles,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : SingleAccountListProducer {
|
||||
|
||||
|
|
@ -51,18 +53,9 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
|
|||
return walletAccountListFlowFactory.create(walletId)
|
||||
.map { accountList ->
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(id = walletId)
|
||||
val isPaymentSupported = userWallet.isPaymentAccountSupported()
|
||||
logger.i(
|
||||
"produce()[$walletId]: userWallet resolved (type=${userWallet::class.simpleName}), " +
|
||||
"isPaymentAccountSupported=$isPaymentSupported",
|
||||
)
|
||||
if (isPaymentSupported) {
|
||||
accountList.plus(Account.Payment(walletId)).getOrElse { throwable ->
|
||||
error("Can not combine account list and payment account status: $throwable")
|
||||
}
|
||||
} else {
|
||||
accountList
|
||||
}
|
||||
accountList
|
||||
.addAccountIf(userWallet.isPaymentAccountSupported()) { Account.Payment(walletId) }
|
||||
.addAccountIf(userWallet.isVirtualAccountSupported()) { Account.Virtual(walletId) }
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
|
@ -72,6 +65,25 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
|
|||
is UserWallet.Hot -> hotWalletId.authType != HotWalletId.AuthType.NoPassword
|
||||
}
|
||||
|
||||
private fun UserWallet.isVirtualAccountSupported(): Boolean {
|
||||
if (!virtualAccountsFeatureToggles.isVirtualAccountsEnabled) return false
|
||||
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> scanResponse.card.firmwareVersion >= FirmwareVersion.HDWalletAvailable
|
||||
is UserWallet.Hot -> hotWalletId.authType != HotWalletId.AuthType.NoPassword
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AccountList.addAccountIf(condition: Boolean, account: () -> Account): AccountList {
|
||||
return if (condition) {
|
||||
plus(account()).getOrElse { throwable ->
|
||||
error("Can not combine account list and special account: $throwable")
|
||||
}
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : SingleAccountListProducer.Factory {
|
||||
override fun create(params: SingleAccountListProducer.Params): DefaultSingleAccountListProducer
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
package com.tangem.data.account.producer
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.core.flow.FlowProducerTools
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.virtualaccount.VirtualAccountFeatureToggles
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
|
|
@ -40,12 +43,16 @@ class DefaultSingleAccountListProducerTest {
|
|||
private val userWalletsListRepository = mockk<UserWalletsListRepository> {
|
||||
every { userWallets } returns MutableStateFlow<List<UserWallet>?>(value = listOf(userWallet))
|
||||
}
|
||||
private val virtualAccountsFeatureToggles = mockk<VirtualAccountFeatureToggles> {
|
||||
every { isVirtualAccountsEnabled } returns false
|
||||
}
|
||||
|
||||
private val producer = DefaultSingleAccountListProducer(
|
||||
params = SingleAccountListProducer.Params(userWalletId = userWalletId),
|
||||
walletAccountListFlowFactory = walletAccountListFlowFactory,
|
||||
flowProducerTools = flowProducerTools,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
virtualAccountsFeatureToggles = virtualAccountsFeatureToggles,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
|
|
@ -72,6 +79,45 @@ class DefaultSingleAccountListProducerTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN virtual accounts enabled WHEN produce THEN account list contains virtual account`() = runTest {
|
||||
// Arrange
|
||||
val supportedWallet = mockk<UserWallet.Hot> {
|
||||
every { walletId } returns userWalletId
|
||||
every { hotWalletId } returns mockk {
|
||||
every { authType } returns HotWalletId.AuthType.Password
|
||||
}
|
||||
}
|
||||
val userWalletsListRepository = mockk<UserWalletsListRepository> {
|
||||
every { userWallets } returns MutableStateFlow<List<UserWallet>?>(value = listOf(supportedWallet))
|
||||
}
|
||||
val virtualAccountsFeatureToggles = mockk<VirtualAccountFeatureToggles> {
|
||||
every { isVirtualAccountsEnabled } returns true
|
||||
}
|
||||
val producer = DefaultSingleAccountListProducer(
|
||||
params = SingleAccountListProducer.Params(userWalletId = userWalletId),
|
||||
walletAccountListFlowFactory = walletAccountListFlowFactory,
|
||||
flowProducerTools = flowProducerTools,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
virtualAccountsFeatureToggles = virtualAccountsFeatureToggles,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
val accountList = AccountList.empty(userWalletId)
|
||||
every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList)
|
||||
|
||||
// Act
|
||||
val actual = producer.produce().let(::getEmittedValues)
|
||||
|
||||
// Assert
|
||||
val expected = accountList
|
||||
.plus(Account.Payment(userWalletId))
|
||||
.getOrElse { error("Unable to add payment account: $it") }
|
||||
.plus(Account.Virtual(userWalletId))
|
||||
.getOrElse { error("Unable to add virtual account: $it") }
|
||||
Truth.assertThat(actual).containsExactly(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `flow will updated if factoryFlow is updated`() = runTest {
|
||||
// Arrange
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue