diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt index ca9bb24e80..c9b24eeb0a 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt @@ -26,6 +26,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.runCatching import com.tangem.utils.isNullOrZero import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.withContext @Suppress("LongParameterList") @@ -134,8 +135,10 @@ internal class DefaultRampManager( userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency, ): ExchangeableState { + val asset = expressServiceLoader.getInitializationStatus(userWalletId).firstOrNull() + ?: return ExchangeableState.Error return withContext(dispatchers.io) { - when (val asset = expressServiceLoader.getInitializationStatus(userWalletId).value) { + when (asset) { is Lce.Error -> ExchangeableState.Error is Lce.Loading -> ExchangeableState.Loading is Lce.Content -> { diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt index cf51b2b006..0799c40b41 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt @@ -1,12 +1,23 @@ package com.tangem.datasource.di +import android.content.Context +import androidx.datastore.core.DataStoreFactory +import androidx.datastore.dataStoreFile +import com.squareup.moshi.Moshi +import com.tangem.datasource.api.express.models.response.Asset import com.tangem.datasource.local.datastore.RuntimeDataStore import com.tangem.datasource.local.token.DefaultExpressAssetsStore import com.tangem.datasource.local.token.ExpressAssetsStore +import com.tangem.datasource.utils.MoshiDataStoreSerializer +import com.tangem.datasource.utils.mapWithStringKeyTypes +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -15,7 +26,22 @@ internal object ExpressAssetsStoreModule { @Provides @Singleton - fun provideExpressAssetsStore(): ExpressAssetsStore { - return DefaultExpressAssetsStore(dataStore = RuntimeDataStore()) + fun provideExpressAssetsStore( + @NetworkMoshi moshi: Moshi, + @ApplicationContext context: Context, + dispatchers: CoroutineDispatcherProvider, + ): ExpressAssetsStore { + return DefaultExpressAssetsStore( + persistenceStore = DataStoreFactory.create( + serializer = MoshiDataStoreSerializer( + moshi = moshi, + types = mapWithStringKeyTypes(), + defaultValue = emptyMap(), + ), + produceFile = { context.dataStoreFile("express_assets") }, + scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + ), + runtimeStore = RuntimeDataStore(), + ) } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/DefaultExpressServiceLoader.kt b/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/DefaultExpressServiceLoader.kt index c2818ecd87..b966a12e0e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/DefaultExpressServiceLoader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/DefaultExpressServiceLoader.kt @@ -12,7 +12,9 @@ import com.tangem.domain.core.utils.lceError import com.tangem.domain.core.utils.lceLoading import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import timber.log.Timber @@ -41,8 +43,6 @@ internal class DefaultExpressServiceLoader @Inject constructor( withContext(dispatchers.io) { val initializationStatus = getInitializationStatusInternal(userWalletId) - initializationStatus.update { lceLoading() } - try { if (userTokens.isNotEmpty()) { val response = tangemExpressApi.getAssets( @@ -54,22 +54,24 @@ internal class DefaultExpressServiceLoader @Inject constructor( initializationStatus.update { response.lceContent() } } } catch (e: Throwable) { - initializationStatus.update { e.lceError() } + if (expressAssetsStore.getSyncOrNull(userWalletId) == null) { + initializationStatus.update { e.lceError() } + } Timber.e(e, "Unable to fetch assets for: ${userWalletId.stringValue}") } } } - override fun getInitializationStatus(userWalletId: UserWalletId): InitializationStatusFlow { - return getInitializationStatusInternal(userWalletId) + override fun getInitializationStatus(userWalletId: UserWalletId): Flow>> { + return flow { getInitializationStatusInternal(userWalletId).collect { emit(it) } } } - private fun getInitializationStatusInternal(userWalletId: UserWalletId): InitializationStatusFlow { + private suspend fun getInitializationStatusInternal(userWalletId: UserWalletId): InitializationStatusFlow { val initializationStatus = initializationStatuses.value.get(key = userWalletId) - if (initializationStatus != null) return initializationStatus - val default: InitializationStatusFlow = MutableStateFlow(value = lceLoading()) + val cached = expressAssetsStore.getSyncOrNull(userWalletId) + val default: InitializationStatusFlow = MutableStateFlow(value = cached?.lceContent() ?: lceLoading()) initializationStatuses.update { it.toMutableMap().apply { diff --git a/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/ExpressServiceLoader.kt b/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/ExpressServiceLoader.kt index 72e59dba3a..f73ee82700 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/ExpressServiceLoader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/exchangeservice/swap/ExpressServiceLoader.kt @@ -4,7 +4,7 @@ import com.tangem.datasource.api.express.models.request.LeastTokenInfo import com.tangem.datasource.api.express.models.response.Asset import com.tangem.domain.core.lce.Lce import com.tangem.domain.wallets.models.UserWalletId -import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.Flow /** * Express service loader @@ -17,5 +17,5 @@ interface ExpressServiceLoader { suspend fun update(userWalletId: UserWalletId, userTokens: List) /** Get initialization status by [userWalletId] */ - fun getInitializationStatus(userWalletId: UserWalletId): StateFlow>> + fun getInitializationStatus(userWalletId: UserWalletId): Flow>> } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultExpressAssetsStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultExpressAssetsStore.kt index c67abc06e5..5d941ccc5f 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultExpressAssetsStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultExpressAssetsStore.kt @@ -1,18 +1,53 @@ package com.tangem.datasource.local.token +import androidx.datastore.core.DataStore import com.tangem.datasource.api.express.models.response.Asset import com.tangem.datasource.local.datastore.core.StringKeyDataStore import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.launch + +internal typealias AssetsByWalletId = Map> internal class DefaultExpressAssetsStore( - private val dataStore: StringKeyDataStore>, + private val persistenceStore: DataStore, + private val runtimeStore: StringKeyDataStore>, ) : ExpressAssetsStore { override suspend fun getSyncOrNull(userWalletId: UserWalletId): List? { - return dataStore.getSyncOrNull(userWalletId.stringValue) + val runtimeAssets = runtimeStore.getSyncOrNull(userWalletId.stringValue) + + if (runtimeAssets != null) { + return runtimeAssets + } + + val cachedAssets = getCachedAssets(userWalletId) + + return if (cachedAssets != null) { + runtimeStore.store(userWalletId.stringValue, cachedAssets) + cachedAssets + } else { + null + } + } + + private suspend fun getCachedAssets(userWalletId: UserWalletId): List? { + return persistenceStore.data.firstOrNull().orEmpty()[userWalletId.stringValue] } override suspend fun store(userWalletId: UserWalletId, item: List) { - dataStore.store(userWalletId.stringValue, item) + coroutineScope { + launch { + runtimeStore.store(userWalletId.stringValue, item) + } + launch { + persistenceStore.updateData { + it.toMutableMap().apply { + put(userWalletId.stringValue, item) + } + } + } + } } } \ No newline at end of file