Updated on 2026-08-14
This commit is contained in:
parent
4bb8d20301
commit
3fd8b110ef
4 changed files with 168 additions and 16 deletions
|
|
@ -24,17 +24,18 @@ dependencies {
|
|||
// endregion
|
||||
|
||||
// region Project - Domain
|
||||
implementation(projects.domain.account)
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.core)
|
||||
implementation(projects.domain.demo)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.walletManager)
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.staking)
|
||||
implementation(projects.domain.staking.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.walletManager)
|
||||
implementation(projects.domain.wallets.models)
|
||||
// endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.data.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.core.utils.catchOn
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher.Params
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
||||
/**
|
||||
* Implementation of [MultiWalletCryptoCurrenciesFetcher] that fetches crypto currencies of all accounts
|
||||
*
|
||||
* @property userWalletsStore [UserWallet]'s store
|
||||
* @property walletAccountsFetcher instance of [WalletAccountsFetcher] to fetch accounts for a multi wallet
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class AccountListCryptoCurrenciesFetcher(
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val walletAccountsFetcher: WalletAccountsFetcher,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MultiWalletCryptoCurrenciesFetcher {
|
||||
|
||||
override suspend fun invoke(params: Params) = Either.catchOn(dispatchers.default) {
|
||||
val userWallet = userWalletsStore.getSyncStrict(key = params.userWalletId)
|
||||
|
||||
if (!userWallet.isMultiCurrency) error("${this::class.simpleName} supports only multi-currency wallet")
|
||||
|
||||
walletAccountsFetcher.fetch(userWalletId = params.userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,16 @@
|
|||
package com.tangem.data.tokens.di
|
||||
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
import com.tangem.data.tokens.AccountListCryptoCurrenciesFetcher
|
||||
import com.tangem.data.tokens.DefaultMultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.data.tokens.utils.CustomTokensMerger
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -24,28 +27,38 @@ internal class MultiWalletCryptoCurrenciesFetcherModule {
|
|||
@Singleton
|
||||
@Provides
|
||||
fun provideMultiWalletCryptoCurrenciesFetcher(
|
||||
accountsFeatureToggles: AccountsFeatureToggles,
|
||||
tangemTechApi: TangemTechApi,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
userTokensResponseStore: UserTokensResponseStore,
|
||||
userTokensSaver: UserTokensSaver,
|
||||
cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
|
||||
expressServiceLoader: ExpressServiceLoader,
|
||||
walletAccountsFetcher: WalletAccountsFetcher,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): MultiWalletCryptoCurrenciesFetcher {
|
||||
return DefaultMultiWalletCryptoCurrenciesFetcher(
|
||||
demoConfig = DemoConfig(),
|
||||
userWalletsStore = userWalletsStore,
|
||||
tangemTechApi = tangemTechApi,
|
||||
customTokensMerger = CustomTokensMerger(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userTokensSaver = userTokensSaver,
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
AccountListCryptoCurrenciesFetcher(
|
||||
userWalletsStore = userWalletsStore,
|
||||
walletAccountsFetcher = walletAccountsFetcher,
|
||||
dispatchers = dispatchers,
|
||||
),
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
userTokensSaver = userTokensSaver,
|
||||
cardCryptoCurrencyFactory = cardCryptoCurrencyFactory,
|
||||
expressServiceLoader = expressServiceLoader,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
DefaultMultiWalletCryptoCurrenciesFetcher(
|
||||
demoConfig = DemoConfig(),
|
||||
userWalletsStore = userWalletsStore,
|
||||
tangemTechApi = tangemTechApi,
|
||||
customTokensMerger = CustomTokensMerger(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userTokensSaver = userTokensSaver,
|
||||
dispatchers = dispatchers,
|
||||
),
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
userTokensSaver = userTokensSaver,
|
||||
cardCryptoCurrencyFactory = cardCryptoCurrencyFactory,
|
||||
expressServiceLoader = expressServiceLoader,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package com.tangem.data.tokens
|
||||
|
||||
import arrow.core.left
|
||||
import com.tangem.common.test.utils.assertEither
|
||||
import com.tangem.common.test.utils.assertEitherRight
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
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.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class AccountListCryptoCurrenciesFetcherTest {
|
||||
|
||||
private val userWalletsStore: UserWalletsStore = mockk(relaxUnitFun = true)
|
||||
private val walletAccountsFetcher: WalletAccountsFetcher = mockk(relaxUnitFun = true)
|
||||
private val dispatchers = TestingCoroutineDispatcherProvider()
|
||||
|
||||
private val fetcher = AccountListCryptoCurrenciesFetcher(
|
||||
userWalletsStore = userWalletsStore,
|
||||
walletAccountsFetcher = walletAccountsFetcher,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(userWalletsStore, walletAccountsFetcher)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns failure if wallet is not multi-currency`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)
|
||||
val mockUserWallet = mockk<UserWallet> { every { isMultiCurrency } returns false }
|
||||
every { userWalletsStore.getSyncStrict(key = params.userWalletId) } returns mockUserWallet
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = IllegalStateException(
|
||||
"${AccountListCryptoCurrenciesFetcher::class.simpleName} supports only multi-currency wallet",
|
||||
).left()
|
||||
assertEither(actual, expected)
|
||||
|
||||
verify { userWalletsStore.getSyncStrict(key = params.userWalletId) }
|
||||
coVerify(inverse = true) { walletAccountsFetcher.fetch(any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns accounts if wallet is multi-currency`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)
|
||||
val mockUserWallet = mockk<UserWallet> { every { isMultiCurrency } returns true }
|
||||
|
||||
every { userWalletsStore.getSyncStrict(key = params.userWalletId) } returns mockUserWallet
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
assertEitherRight(actual)
|
||||
|
||||
coVerify(ordering = Ordering.SEQUENCE) {
|
||||
userWalletsStore.getSyncStrict(key = params.userWalletId)
|
||||
walletAccountsFetcher.fetch(userWalletId = params.userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns error if walletAccountsFetcher returns error`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)
|
||||
val mockUserWallet = mockk<UserWallet> { every { isMultiCurrency } returns true }
|
||||
val error = RuntimeException("fetch error")
|
||||
|
||||
every { userWalletsStore.getSyncStrict(key = params.userWalletId) } returns mockUserWallet
|
||||
coEvery { walletAccountsFetcher.fetch(userWalletId = params.userWalletId) } throws error
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = error.left()
|
||||
assertEither(actual, expected)
|
||||
|
||||
coVerify(ordering = Ordering.SEQUENCE) {
|
||||
userWalletsStore.getSyncStrict(key = params.userWalletId)
|
||||
walletAccountsFetcher.fetch(userWalletId = params.userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val userWalletId = UserWalletId("012")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue