Updated on 2026-08-14
This commit is contained in:
parent
e2721b21e1
commit
a67ca6279f
14 changed files with 24 additions and 614 deletions
|
|
@ -1,71 +0,0 @@
|
|||
package com.tangem.data.account.producer
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.some
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.getSyncStrict
|
||||
import com.tangem.domain.core.flow.FlowProducerTools
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
* Default implementation of [MultiWalletCryptoCurrenciesProducer]
|
||||
*
|
||||
* @property params params
|
||||
* @property flowProducerTools tools for producing flows
|
||||
* @property userWalletsListRepository repository for getting user wallets
|
||||
* @property userTokensResponseStore store of `UserTokensResponse`
|
||||
* @property responseCryptoCurrenciesFactory factory for creating [CryptoCurrency] from `UserTokensResponse`
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultMultiWalletCryptoCurrenciesProducer @AssistedInject constructor(
|
||||
@Assisted val params: MultiWalletCryptoCurrenciesProducer.Params,
|
||||
override val flowProducerTools: FlowProducerTools,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val userTokensResponseStore: UserTokensResponseStore,
|
||||
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MultiWalletCryptoCurrenciesProducer {
|
||||
|
||||
override val fallback: Option<Set<CryptoCurrency>> = emptySet<CryptoCurrency>().some()
|
||||
|
||||
override fun produce(): Flow<Set<CryptoCurrency>> {
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(id = params.userWalletId)
|
||||
|
||||
if (!userWallet.isMultiCurrency) {
|
||||
error("${this::class.simpleName ?: this::class.toString()} supports only multi-currency wallet")
|
||||
}
|
||||
|
||||
return userTokensResponseStore.get(userWalletId = params.userWalletId)
|
||||
.distinctUntilChanged()
|
||||
.map { response ->
|
||||
if (response == null) return@map emptySet()
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = response,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
).toSet()
|
||||
}
|
||||
.onEmpty { emit(emptySet()) }
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MultiWalletCryptoCurrenciesProducer.Factory {
|
||||
override fun create(
|
||||
params: MultiWalletCryptoCurrenciesProducer.Params,
|
||||
): DefaultMultiWalletCryptoCurrenciesProducer
|
||||
}
|
||||
}
|
||||
|
|
@ -1,378 +0,0 @@
|
|||
package com.tangem.data.account.producer
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.card.configs.GenericCardConfig
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.core.flow.FlowProducerTools
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
|
||||
private val params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWallet.walletId)
|
||||
private val userWalletsListRepository: UserWalletsListRepository = mockk(relaxUnitFun = true)
|
||||
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxUnitFun = true)
|
||||
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory = mockk()
|
||||
private val flowProducerTools: FlowProducerTools = mockk()
|
||||
|
||||
private val producer = DefaultMultiWalletCryptoCurrenciesProducer(
|
||||
params = params,
|
||||
flowProducerTools = flowProducerTools,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(userWalletsListRepository, userTokensResponseStore, responseCryptoCurrenciesFactory)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `flow is mapped for user wallet id from params`() = runTest {
|
||||
// Arrange
|
||||
val userTokensResponseFlow = flowOf<UserTokensResponse?>(null)
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
every { userTokensResponseStore.get(params.userWalletId) } returns userTokensResponseFlow
|
||||
|
||||
// Act
|
||||
val actual = producer.produce().let(::getEmittedValues)
|
||||
|
||||
// Assert
|
||||
val expected = emptySet<CryptoCurrency>()
|
||||
|
||||
Truth.assertThat(actual.size).isEqualTo(1)
|
||||
Truth.assertThat(actual.first()).isEqualTo(expected)
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets
|
||||
userTokensResponseStore.get(params.userWalletId)
|
||||
}
|
||||
|
||||
verify(inverse = true) {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any(), accountIndex = any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `flow will updated if UserTokensResponse is updated`() = runTest {
|
||||
// Arrange
|
||||
val userTokensResponseFlow = MutableSharedFlow<UserTokensResponse>(replay = 2)
|
||||
|
||||
val userTokensResponse = UserTokensResponse(
|
||||
group = UserTokensResponse.GroupType.TOKEN,
|
||||
sort = UserTokensResponse.SortType.MARKETCAP,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
val cryptoCurrencies = emptySet<CryptoCurrency>()
|
||||
|
||||
val updatedUserTokensResponse = UserTokensResponse(
|
||||
group = UserTokensResponse.GroupType.TOKEN,
|
||||
sort = UserTokensResponse.SortType.MARKETCAP,
|
||||
tokens = listOf(
|
||||
UserTokensResponse.Token(
|
||||
id = null,
|
||||
networkId = "bitcoin",
|
||||
derivationPath = null,
|
||||
name = "Bitcoin",
|
||||
symbol = "BTC",
|
||||
decimals = 8,
|
||||
contractAddress = null,
|
||||
addresses = listOf(),
|
||||
),
|
||||
),
|
||||
)
|
||||
val updatedCryptoCurrencies = setOf(
|
||||
cryptoCurrencyFactory.createCoin(Blockchain.Bitcoin),
|
||||
)
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
every { userTokensResponseStore.get(params.userWalletId) } returns userTokensResponseFlow
|
||||
|
||||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = updatedUserTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
} returns updatedCryptoCurrencies.toList()
|
||||
|
||||
val producerFlow = producer.produce()
|
||||
|
||||
// Act 1 (first emit)
|
||||
userTokensResponseFlow.emit(userTokensResponse)
|
||||
|
||||
val actual1 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected1 = cryptoCurrencies
|
||||
|
||||
Truth.assertThat(actual1.size).isEqualTo(1)
|
||||
Truth.assertThat(actual1.first()).isEqualTo(expected1)
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets
|
||||
userTokensResponseStore.get(params.userWalletId)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
|
||||
// Act 2 (second emit)
|
||||
userTokensResponseFlow.emit(updatedUserTokensResponse)
|
||||
|
||||
val actual2 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected2 = listOf(cryptoCurrencies, updatedCryptoCurrencies)
|
||||
|
||||
Truth.assertThat(actual2.size).isEqualTo(2)
|
||||
Truth.assertThat(actual2).isEqualTo(expected2)
|
||||
|
||||
verifyOrder {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = updatedUserTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `flow is filtered the same status`() = runTest {
|
||||
// Arrange
|
||||
val userTokensResponseFlow = MutableSharedFlow<UserTokensResponse>(replay = 2)
|
||||
|
||||
val userTokensResponse = UserTokensResponse(
|
||||
group = UserTokensResponse.GroupType.TOKEN,
|
||||
sort = UserTokensResponse.SortType.MARKETCAP,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
|
||||
val cryptoCurrencies = emptySet<CryptoCurrency>()
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
every { userTokensResponseStore.get(params.userWalletId) } returns userTokensResponseFlow
|
||||
|
||||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
val producerFlow = producer.produce()
|
||||
|
||||
// Act 1 (first emit)
|
||||
userTokensResponseFlow.emit(userTokensResponse)
|
||||
|
||||
val actual1 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected1 = cryptoCurrencies
|
||||
|
||||
Truth.assertThat(actual1.size).isEqualTo(1)
|
||||
Truth.assertThat(actual1.first()).isEqualTo(expected1)
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets
|
||||
userTokensResponseStore.get(params.userWalletId)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
|
||||
// Act 2 (second emit)
|
||||
userTokensResponseFlow.emit(userTokensResponse)
|
||||
|
||||
val actual2 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected2 = expected1
|
||||
Truth.assertThat(actual2.size).isEqualTo(1)
|
||||
Truth.assertThat(actual2.first()).isEqualTo(expected2)
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
fun `flow throws exception`() = runTest {
|
||||
// Arrange
|
||||
val exception = IllegalStateException()
|
||||
|
||||
val userTokensResponse = UserTokensResponse(
|
||||
group = UserTokensResponse.GroupType.TOKEN,
|
||||
sort = UserTokensResponse.SortType.MARKETCAP,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
|
||||
val cryptoCurrencies = emptySet<CryptoCurrency>()
|
||||
|
||||
val innerFlow = MutableStateFlow(value = false)
|
||||
val userTokensResponseFlow = flow {
|
||||
if (innerFlow.value) {
|
||||
emit(userTokensResponse)
|
||||
} else {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
.buffer(capacity = 5)
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
every { userTokensResponseStore.get(params.userWalletId) } returns userTokensResponseFlow
|
||||
|
||||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
val producerFlow = producer.produceWithFallback()
|
||||
|
||||
// Act 1 (fallback)
|
||||
val actual1 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected1 = producer.fallback.getOrNull()
|
||||
Truth.assertThat(actual1.size).isEqualTo(1)
|
||||
Truth.assertThat(actual1.first()).isEqualTo(expected1)
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets
|
||||
userTokensResponseStore.get(params.userWalletId)
|
||||
}
|
||||
|
||||
// Act 2 (emit)
|
||||
innerFlow.emit(value = true)
|
||||
val actual2 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert
|
||||
val expected2 = cryptoCurrencies
|
||||
Truth.assertThat(actual2.size).isEqualTo(1)
|
||||
Truth.assertThat(actual2.first()).isEqualTo(expected2)
|
||||
|
||||
verifyOrder {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `flow is empty if store returns empty flow`() = runTest {
|
||||
// Arrange
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
every { userTokensResponseStore.get(params.userWalletId) } returns emptyFlow()
|
||||
|
||||
// Act
|
||||
val actual = producer.produce().let(::getEmittedValues)
|
||||
|
||||
// Assert
|
||||
val expected = producer.fallback.getOrNull()
|
||||
Truth.assertThat(actual.size).isEqualTo(1)
|
||||
Truth.assertThat(actual.first()).isEqualTo(expected)
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets
|
||||
userTokensResponseStore.get(params.userWalletId)
|
||||
}
|
||||
|
||||
verify(inverse = true) {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any(), accountIndex = any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `produce throws exception if UserWallet isn't multi-currency wallet`() = runTest {
|
||||
// Arrange
|
||||
val mockUserWallet = mockk<UserWallet> {
|
||||
every { walletId } returns userWallet.walletId
|
||||
every { isMultiCurrency } returns false
|
||||
}
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(mockUserWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
|
||||
// Act
|
||||
val actual = runCatching { producer.produce() }.exceptionOrNull()
|
||||
|
||||
// Assert
|
||||
val expected = IllegalStateException(
|
||||
"${DefaultMultiWalletCryptoCurrenciesProducer::class.simpleName} supports only multi-currency wallet",
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isInstanceOf(expected::class.java)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(expected.message)
|
||||
|
||||
verifyOrder { userWalletsListRepository.userWallets }
|
||||
|
||||
verify(inverse = true) {
|
||||
userTokensResponseStore.get(any())
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any(), accountIndex = any())
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
val scanResponse = MockScanResponseFactory.create(
|
||||
cardConfig = GenericCardConfig(2),
|
||||
derivedKeys = emptyMap(),
|
||||
)
|
||||
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse = scanResponse)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,12 @@
|
|||
package com.tangem.data.common.currency
|
||||
|
||||
import com.tangem.data.common.api.safeApiCall
|
||||
import com.tangem.data.common.tokens.UserTokensBackwardCompatibility
|
||||
import com.tangem.data.common.wallet.WalletServerBinder
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.common.response.isNetworkError
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.getSyncOrNull
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -23,31 +21,11 @@ import timber.log.Timber
|
|||
class UserTokensSaver(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val userTokensResponseStore: UserTokensResponseStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val addressesEnricher: UserTokensResponseAddressesEnricher,
|
||||
private val walletServerBinder: WalletServerBinder,
|
||||
private val pushTokensRetryerPool: RetryerPool,
|
||||
) {
|
||||
private val userTokensBackwardCompatibility = UserTokensBackwardCompatibility()
|
||||
|
||||
suspend fun storeAndPush(userWalletId: UserWalletId, response: UserTokensResponse) {
|
||||
withContext(dispatchers.default) {
|
||||
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = true)
|
||||
|
||||
store(userWalletId = userWalletId, response = enrichedResponse, useEnricher = false)
|
||||
push(userWalletId = userWalletId, response = enrichedResponse, useEnricher = false)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, response: UserTokensResponse, useEnricher: Boolean = true) =
|
||||
withContext(dispatchers.default) {
|
||||
val updatedResponse = response
|
||||
.applyCompatibility()
|
||||
.enrichIf(userWalletId = userWalletId, condition = useEnricher)
|
||||
|
||||
userTokensResponseStore.store(userWalletId = userWalletId, response = updatedResponse)
|
||||
}
|
||||
|
||||
suspend fun push(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -111,10 +89,6 @@ class UserTokensSaver(
|
|||
)
|
||||
}
|
||||
|
||||
private fun UserTokensResponse.applyCompatibility(): UserTokensResponse {
|
||||
return userTokensBackwardCompatibility.applyCompatibilityAndGetUpdated(userTokensResponse = this)
|
||||
}
|
||||
|
||||
private suspend fun UserTokensResponse.enrichIf(
|
||||
userWalletId: UserWalletId,
|
||||
condition: Boolean,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.data.common.wallet.WalletServerBinder
|
|||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -67,7 +66,6 @@ internal object DataCommonModule {
|
|||
fun provideUserTokensSaver(
|
||||
tangemTechApi: TangemTechApi,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
userTokensResponseStore: UserTokensResponseStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
addressesEnricher: UserTokensResponseAddressesEnricher,
|
||||
walletServerBinder: WalletServerBinder,
|
||||
|
|
@ -75,7 +73,6 @@ internal object DataCommonModule {
|
|||
return UserTokensSaver(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
dispatchers = dispatchers,
|
||||
addressesEnricher = addressesEnricher,
|
||||
pushTokensRetryerPool = RetryerPool(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.datasource.api.common.response.ApiResponseError
|
|||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -23,14 +22,12 @@ class UserTokensSaverTest {
|
|||
|
||||
private val tangemTechApi: TangemTechApi = mockk()
|
||||
private val userWalletsListRepository: UserWalletsListRepository = mockk(relaxUnitFun = true)
|
||||
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxed = true)
|
||||
private val enricher: UserTokensResponseAddressesEnricher = mockk()
|
||||
private val walletServerBinder: WalletServerBinder = mockk()
|
||||
|
||||
private val userTokensSaver: UserTokensSaver = UserTokensSaver(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
addressesEnricher = enricher,
|
||||
walletServerBinder = walletServerBinder,
|
||||
|
|
@ -42,46 +39,11 @@ class UserTokensSaverTest {
|
|||
clearMocks(
|
||||
tangemTechApi,
|
||||
userWalletsListRepository,
|
||||
userTokensResponseStore,
|
||||
enricher,
|
||||
walletServerBinder,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN user wallet id and response WHEN store THEN should store enriched response`() = runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val response = UserTokensResponse(
|
||||
version = 0,
|
||||
group = UserTokensResponse.GroupType.NETWORK,
|
||||
sort = UserTokensResponse.SortType.BALANCE,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
|
||||
val enrichedResponse = UserTokensResponse(
|
||||
version = 0,
|
||||
group = UserTokensResponse.GroupType.NETWORK,
|
||||
sort = UserTokensResponse.SortType.MANUAL,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
|
||||
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
||||
|
||||
// WHEN
|
||||
userTokensSaver.store(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
coVerifyOrder {
|
||||
enricher(userWalletId, response)
|
||||
userTokensResponseStore.store(userWalletId, enrichedResponse)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
tangemTechApi.saveTokens(any(), any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN user wallet id and response WHEN push AND api call fails THEN should log error and call onFailSend`() =
|
||||
runTest {
|
||||
|
|
@ -133,49 +95,4 @@ class UserTokensSaverTest {
|
|||
|
||||
assert(onFailSendCalled) { "onFailSend callback should be called when API call fails" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN user wallet id and response WHEN storeAndPush THEN should store and push enriched response`() = runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val userWallet = mockk<UserWallet.Cold> {
|
||||
every { this@mockk.walletId } returns userWalletId
|
||||
every { this@mockk.name } returns "Wallet"
|
||||
}
|
||||
|
||||
val response = UserTokensResponse(
|
||||
version = 0,
|
||||
group = UserTokensResponse.GroupType.NETWORK,
|
||||
sort = UserTokensResponse.SortType.BALANCE,
|
||||
tokens = emptyList(),
|
||||
walletName = userWallet.name,
|
||||
walletType = WalletType.COLD,
|
||||
)
|
||||
val enrichedResponse = UserTokensResponse(
|
||||
version = 0,
|
||||
group = UserTokensResponse.GroupType.NETWORK,
|
||||
sort = UserTokensResponse.SortType.BALANCE,
|
||||
tokens = emptyList(),
|
||||
walletName = userWallet.name,
|
||||
walletType = WalletType.COLD,
|
||||
)
|
||||
|
||||
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns userWalletsFlow
|
||||
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
||||
coEvery {
|
||||
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
|
||||
} returns ApiResponse.Success(Unit)
|
||||
|
||||
// WHEN
|
||||
userTokensSaver.storeAndPush(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
coVerifyOrder {
|
||||
enricher(userWalletId, response)
|
||||
userWalletsListRepository.userWallets
|
||||
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue