Updated on 2026-08-14
This commit is contained in:
parent
55f731f1c3
commit
b89d98aa35
12 changed files with 358 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ import com.tangem.data.common.currency.CardCryptoCurrencyFactory
|
|||
import com.tangem.data.networks.repository.DefaultNetworksRepository
|
||||
import com.tangem.data.networks.store.DefaultNetworksStatusesStore
|
||||
import com.tangem.data.networks.store.NetworksStatusesStore
|
||||
import com.tangem.data.networks.utils.DefaultNetworksCleaner
|
||||
import com.tangem.datasource.di.NetworkMoshi
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.datasource.local.network.entity.NetworkStatusDM
|
||||
|
|
@ -15,6 +16,7 @@ import com.tangem.datasource.utils.MoshiDataStoreSerializer
|
|||
import com.tangem.datasource.utils.mapWithStringKeyTypes
|
||||
import com.tangem.datasource.utils.setTypes
|
||||
import com.tangem.domain.networks.repository.NetworksRepository
|
||||
import com.tangem.domain.networks.utils.NetworksCleaner
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
@ -67,4 +69,18 @@ internal object NetworkDataModule {
|
|||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideNetworksCleaner(
|
||||
networksStatusesStore: NetworksStatusesStore,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): NetworksCleaner {
|
||||
return DefaultNetworksCleaner(
|
||||
networksStatusesStore = networksStatusesStore,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -96,6 +96,20 @@ internal class DefaultNetworksStatusesStore(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun clear(userWalletId: UserWalletId, networks: Set<Network>) {
|
||||
persistenceDataStore.updateData { storedStatuses ->
|
||||
storedStatuses.toMutableMap().apply {
|
||||
val updatedValues = this[userWalletId.stringValue].orEmpty().filterNot {
|
||||
networks.any { network ->
|
||||
it.networkId.value == network.rawId && it.derivationPath.value == network.derivationPath.value
|
||||
}
|
||||
}
|
||||
|
||||
this[userWalletId.stringValue] = updatedValues.toSet()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateInRuntime(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<Network>,
|
||||
|
|
|
|||
|
|
@ -41,4 +41,7 @@ internal interface NetworksStatusesStore {
|
|||
* See complex methods in `NetworksStatusesStoreExt`.
|
||||
*/
|
||||
suspend fun store(userWalletId: UserWalletId, status: NetworkStatus)
|
||||
|
||||
/** Clear statuses of [networks] by [userWalletId] */
|
||||
suspend fun clear(userWalletId: UserWalletId, networks: Set<Network>)
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.tangem.data.networks.utils
|
||||
|
||||
import com.tangem.data.networks.store.NetworksStatusesStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.networks.utils.NetworksCleaner
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Default implementation of [NetworksCleaner].
|
||||
*
|
||||
* @property networksStatusesStore Store to manage network statuses.
|
||||
* @property walletManagersFacade Facade to manage wallet managers.
|
||||
* @property dispatchers Coroutine dispatchers provider.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultNetworksCleaner(
|
||||
private val networksStatusesStore: NetworksStatusesStore,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : NetworksCleaner {
|
||||
|
||||
override suspend fun invoke(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
withContext(dispatchers.default) {
|
||||
val (networks, tokens) = currencies.partitionByType()
|
||||
|
||||
coroutineScope {
|
||||
launch { cleanStore(userWalletId = userWalletId, networks = networks) }
|
||||
launch { cleanWalletManager(userWalletId = userWalletId, networks = networks, tokens = tokens) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cleanStore(userWalletId: UserWalletId, networks: Set<Network>) {
|
||||
if (networks.isNotEmpty()) {
|
||||
networksStatusesStore.clear(userWalletId = userWalletId, networks = networks)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cleanWalletManager(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<Network>,
|
||||
tokens: Set<CryptoCurrency.Token>,
|
||||
) {
|
||||
if (networks.isNotEmpty()) {
|
||||
walletManagersFacade.remove(userWalletId = userWalletId, networks = networks)
|
||||
}
|
||||
|
||||
if (tokens.isNotEmpty()) {
|
||||
walletManagersFacade.removeTokens(userWalletId = userWalletId, tokens = tokens)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrency>.partitionByType(): Pair<Set<Network>, Set<CryptoCurrency.Token>> {
|
||||
val networks = mutableSetOf<Network>()
|
||||
val tokens = mutableSetOf<CryptoCurrency.Token>()
|
||||
|
||||
for (currency in this) {
|
||||
when (currency) {
|
||||
is CryptoCurrency.Coin -> networks.add(currency.network)
|
||||
is CryptoCurrency.Token -> tokens.add(currency)
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(networks, tokens)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.tangem.data.networks.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.data.networks.store.NetworksStatusesStore
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.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)
|
||||
class DefaultNetworksCleanerTest {
|
||||
|
||||
private val networksStatusesStore = mockk<NetworksStatusesStore>(relaxed = true)
|
||||
private val walletManagersFacade = mockk<WalletManagersFacade>(relaxed = true)
|
||||
private val cleaner = DefaultNetworksCleaner(
|
||||
networksStatusesStore = networksStatusesStore,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
private val userWalletId = UserWalletId("011")
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
private val network = cryptoCurrencyFactory.ethereum.network
|
||||
private val coin = cryptoCurrencyFactory.ethereum
|
||||
private val token = cryptoCurrencyFactory.createToken(Blockchain.Ethereum)
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
clearMocks(networksStatusesStore, walletManagersFacade)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should clear networks and remove managers and tokens when called`() = runTest {
|
||||
// Arrange
|
||||
val currencies = listOf(coin, token)
|
||||
|
||||
// Act
|
||||
cleaner(userWalletId = userWalletId, currencies = currencies)
|
||||
|
||||
// Assert
|
||||
coVerifyOrder {
|
||||
networksStatusesStore.clear(userWalletId, setOf(network))
|
||||
walletManagersFacade.remove(userWalletId = userWalletId, networks = setOf(network))
|
||||
walletManagersFacade.removeTokens(userWalletId = userWalletId, tokens = setOf(token))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should handle empty currencies`() = runTest {
|
||||
// Act
|
||||
cleaner(userWalletId = userWalletId, currencies = emptyList())
|
||||
|
||||
// Assert
|
||||
coVerifyOrder(inverse = true) {
|
||||
networksStatusesStore.clear(userWalletId = any(), networks = any())
|
||||
walletManagersFacade.remove(userWalletId = any(), networks = any())
|
||||
walletManagersFacade.removeTokens(userWalletId = any(), tokens = any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should clear only networks when there are no tokens`() = runTest {
|
||||
val currencies = listOf(coin)
|
||||
|
||||
cleaner(userWalletId = userWalletId, currencies = currencies)
|
||||
|
||||
coVerifyOrder {
|
||||
networksStatusesStore.clear(userWalletId, setOf(network))
|
||||
walletManagersFacade.remove(userWalletId = userWalletId, networks = setOf(network))
|
||||
}
|
||||
|
||||
coVerifyOrder(inverse = true) {
|
||||
walletManagersFacade.removeTokens(userWalletId = any(), tokens = any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should clear only tokens when there are no networks`() = runTest {
|
||||
// Arrange
|
||||
val currencies = listOf(token)
|
||||
|
||||
// Act
|
||||
cleaner(userWalletId = userWalletId, currencies = currencies)
|
||||
|
||||
// Assert
|
||||
coVerifyOrder {
|
||||
walletManagersFacade.removeTokens(userWalletId = userWalletId, tokens = setOf(token))
|
||||
}
|
||||
|
||||
coVerifyOrder(inverse = true) {
|
||||
networksStatusesStore.clear(userWalletId = any(), networks = any())
|
||||
walletManagersFacade.remove(userWalletId = any(), networks = any())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue