diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworksStatusesStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworksStatusesStoreModule.kt index bbf8c38124..62010f5c24 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworksStatusesStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworksStatusesStoreModule.kt @@ -7,7 +7,10 @@ import com.squareup.moshi.Moshi import com.tangem.datasource.local.datastore.RuntimeDataStore import com.tangem.datasource.local.network.DefaultNetworksStatusesStore import com.tangem.datasource.local.network.NetworksStatusesStore -import com.tangem.datasource.local.network.utils.NetworkStatusesSerializer +import com.tangem.datasource.local.network.entity.NetworkStatusDM +import com.tangem.datasource.utils.MoshiDataStoreSerializer +import com.tangem.datasource.utils.mapWithStringKeyTypes +import com.tangem.datasource.utils.setTypes import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -30,7 +33,11 @@ internal object NetworksStatusesStoreModule { return DefaultNetworksStatusesStore( runtimeDataStore = RuntimeDataStore(), persistenceDataStore = DataStoreFactory.create( - serializer = NetworkStatusesSerializer(moshi), + serializer = MoshiDataStoreSerializer( + moshi = moshi, + types = mapWithStringKeyTypes(valueTypes = setTypes()), + defaultValue = emptyMap(), + ), produceFile = { context.dataStoreFile(fileName = "networks_statuses") }, scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), ), diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt index 437628831c..c0ff388721 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt @@ -2,7 +2,7 @@ package com.tangem.datasource.local.network import androidx.datastore.core.DataStore import com.tangem.datasource.local.datastore.RuntimeDataStore -import com.tangem.datasource.local.network.entity.NetworkStatusesDM +import com.tangem.datasource.local.network.entity.NetworkStatusesByWalletId import com.tangem.datasource.local.network.utils.toDataModel import com.tangem.datasource.local.network.utils.toDomainModel import com.tangem.domain.tokens.model.Network @@ -16,7 +16,7 @@ import kotlinx.coroutines.sync.withLock internal class DefaultNetworksStatusesStore( private val runtimeDataStore: RuntimeDataStore>, - private val persistenceDataStore: DataStore, + private val persistenceDataStore: DataStore, ) : NetworksStatusesStore { private val mutex = Mutex() @@ -33,7 +33,7 @@ internal class DefaultNetworksStatusesStore( .firstOrNull { it.id == status.networkId } ?: return@mapNotNullTo null - status.toDomainModel(network) + status.toDomainModel(network = network, isCached = true) } .orEmpty() @@ -110,7 +110,7 @@ internal class DefaultNetworksStatusesStore( persistenceDataStore.updateData { storedStatuses -> val userWalletStatuses = storedStatuses[userWalletId.stringValue] ?: emptySet() - val updatedStatuses = userWalletStatuses.addOrReplace(status.toDataModel(network)) { + val updatedStatuses = userWalletStatuses.addOrReplace(item = status.toDataModel(network)) { it.networkId == network.id } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/entity/NetworkStatusDM.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/entity/NetworkStatusDM.kt index 6c681b5cf8..43c947e55c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/entity/NetworkStatusDM.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/network/entity/NetworkStatusDM.kt @@ -1,27 +1,34 @@ package com.tangem.datasource.local.network.entity +import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.tangem.domain.tokens.model.Network import java.math.BigDecimal -internal typealias NetworkStatusesDM = Map> +internal typealias NetworkStatusesByWalletId = Map> @JsonClass(generateAdapter = true) internal data class NetworkStatusDM( - val networkId: Network.ID, - val selectedAddress: String, - val availableAddresses: Set
, - val amounts: Map, + @Json(name = "network_id") val networkId: Network.ID, + @Json(name = "selected_address") val selectedAddress: String, + @Json(name = "available_addresses") val availableAddresses: Set
, + @Json(name = "amounts") val amounts: Map, ) { @JsonClass(generateAdapter = true) data class Address( - val value: String, - val type: Type, + @Json(name = "value") val value: String, + @Json(name = "type") val type: Type, ) { + @JsonClass(generateAdapter = false) enum class Type { - Primary, Secondary, + + @Json(name = "primary") + Primary, + + @Json(name = "secondary") + Secondary, } } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusMapper.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusMapper.kt index cd0aa4071c..9b8de4a71e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusMapper.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusMapper.kt @@ -32,7 +32,7 @@ internal fun NetworkStatus.Verified.toDataModel(network: Network): NetworkStatus ) } -internal fun NetworkStatusDM.toDomainModel(network: Network): NetworkStatus { +internal fun NetworkStatusDM.toDomainModel(network: Network, isCached: Boolean): NetworkStatus { return NetworkStatus( network = network, value = NetworkStatus.Verified( @@ -40,6 +40,7 @@ internal fun NetworkStatusDM.toDomainModel(network: Network): NetworkStatus { amounts = mapToDomainAmounts(amounts), pendingTransactions = mapOf(), ), + isCached = isCached, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusesSerializer.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusesSerializer.kt deleted file mode 100644 index 487cd016b3..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/utils/NetworkStatusesSerializer.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.tangem.datasource.local.network.utils - -import androidx.datastore.core.Serializer -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types -import com.tangem.datasource.local.network.entity.NetworkStatusDM -import com.tangem.datasource.local.network.entity.NetworkStatusesDM -import java.io.InputStream -import java.io.OutputStream - -internal class NetworkStatusesSerializer(moshi: Moshi) : Serializer { - - private val adapter by lazy { - val type = Types.newParameterizedType( - Map::class.java, - String::class.java, - Types.newParameterizedType(Set::class.java, NetworkStatusDM::class.java), - ) - - moshi.adapter(type) - } - - override val defaultValue: NetworkStatusesDM = emptyMap() - - override suspend fun readFrom(input: InputStream): NetworkStatusesDM { - return input.bufferedReader().use { reader -> - adapter.fromJson(reader.readText()) ?: defaultValue - } - } - - override suspend fun writeTo(t: NetworkStatusesDM, output: OutputStream) { - output.bufferedWriter().use { writer -> - writer.write(adapter.toJson(t)) - } - } -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/MoshiTypesExt.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/MoshiTypesExt.kt index 2330648ff4..cc20669688 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/MoshiTypesExt.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/MoshiTypesExt.kt @@ -3,6 +3,10 @@ package com.tangem.datasource.utils import com.squareup.moshi.Types import java.lang.reflect.ParameterizedType +fun mapWithStringKeyTypes(valueTypes: ParameterizedType): ParameterizedType { + return Types.newParameterizedType(Map::class.java, String::class.java, valueTypes) +} + inline fun mapWithStringKeyTypes(): ParameterizedType { return Types.newParameterizedType(Map::class.java, String::class.java, T::class.java) } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt index 7d219967a7..716ae1da27 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt @@ -120,8 +120,17 @@ internal class DefaultNetworksRepository( refresh: Boolean, ) = coroutineScope { if (refresh) { - val statusesToRefresh = networks.map { NetworkStatus(it, NetworkStatus.Refreshing) } - networksStatusesStore.storeAll(userWalletId, statusesToRefresh) + val statusesToRefresh = networksStatusesStore.getSyncOrNull(userWalletId)?.mapNotNull { + if (it.network in networks) { + it.copy(value = NetworkStatus.Refreshing) + } else { + null + } + } + + if (statusesToRefresh != null) { + networksStatusesStore.storeAll(key = userWalletId, values = statusesToRefresh) + } } val currencies = getCurrencies(userWalletId, networks) diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt index 0aa2528c5c..f3e1ba0f34 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt @@ -36,6 +36,7 @@ internal class NetworkStatusFactory { ), ) }, + isCached = false, ) } diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt index d33b011230..cf693aa286 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt @@ -8,10 +8,12 @@ import java.math.BigDecimal * * @property network The network for which the status is provided. * @property value The specific status value, represented as a sealed class to encapsulate the various possible states of the network. + * @property isCached flag that determines whether the status is a cache */ data class NetworkStatus( val network: Network, val value: Value, + val isCached: Boolean, ) { /** diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt index 903bc4f2ec..e1f5a64040 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt @@ -8,7 +8,6 @@ import com.tangem.domain.tokens.model.NetworkAddress import com.tangem.domain.tokens.model.NetworkStatus import java.math.BigDecimal -@Suppress("MemberVisibilityCanBePrivate") internal object MockNetworks { val amountToCreateAccount: BigDecimal = BigDecimal.TEN @@ -52,17 +51,26 @@ internal object MockNetworks { transactionExtrasType = Network.TransactionExtrasType.NONE, ) - val networkStatus1 = NetworkStatus( + val verifiedNetworksStatuses: NonEmptySet + get() = nonEmptySetOf( + verifiedNetworkStatus1, + verifiedNetworkStatus2, + verifiedNetworkStatus3, + ) + + private val networkStatus1 = NetworkStatus( network = network1, value = NetworkStatus.Unreachable(address = null), + isCached = false, ) - val networkStatus2 = NetworkStatus( + private val networkStatus2 = NetworkStatus( network = network2, value = NetworkStatus.MissedDerivation, + isCached = false, ) - val networkStatus3 = NetworkStatus( + private val networkStatus3 = NetworkStatus( network = network3, value = NetworkStatus.NoAccount( amountToCreateAccount = amountToCreateAccount, @@ -71,11 +79,10 @@ internal object MockNetworks { ), errorMessage = "", ), + isCached = false, ) - val errorNetworksStatuses = nonEmptySetOf(networkStatus1, networkStatus2, networkStatus3) - - val verifiedNetworkStatus1: NetworkStatus + private val verifiedNetworkStatus1: NetworkStatus get() = networkStatus1.copy( value = NetworkStatus.Verified( amounts = mapOf( @@ -90,7 +97,7 @@ internal object MockNetworks { ), ) - val verifiedNetworkStatus2: NetworkStatus + private val verifiedNetworkStatus2: NetworkStatus get() = networkStatus2.copy( value = NetworkStatus.Verified( amounts = mapOf( @@ -105,7 +112,7 @@ internal object MockNetworks { ), ) - val verifiedNetworkStatus3: NetworkStatus + private val verifiedNetworkStatus3: NetworkStatus get() = networkStatus3.copy( value = NetworkStatus.Verified( amounts = mapOf( @@ -120,11 +127,4 @@ internal object MockNetworks { ), ), ) - - val verifiedNetworksStatuses: NonEmptySet - get() = nonEmptySetOf( - verifiedNetworkStatus1, - verifiedNetworkStatus2, - verifiedNetworkStatus3, - ) } \ No newline at end of file