Updated on 2026-08-14
This commit is contained in:
parent
2e14534db3
commit
66c6e8e34d
5 changed files with 82 additions and 16 deletions
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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<Asset>(),
|
||||
defaultValue = emptyMap(),
|
||||
),
|
||||
produceFile = { context.dataStoreFile("express_assets") },
|
||||
scope = CoroutineScope(context = dispatchers.io + SupervisorJob()),
|
||||
),
|
||||
runtimeStore = RuntimeDataStore(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Lce<Throwable, List<Asset>>> {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<LeastTokenInfo>)
|
||||
|
||||
/** Get initialization status by [userWalletId] */
|
||||
fun getInitializationStatus(userWalletId: UserWalletId): StateFlow<Lce<Throwable, List<Asset>>>
|
||||
fun getInitializationStatus(userWalletId: UserWalletId): Flow<Lce<Throwable, List<Asset>>>
|
||||
}
|
||||
|
|
@ -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<String, List<Asset>>
|
||||
|
||||
internal class DefaultExpressAssetsStore(
|
||||
private val dataStore: StringKeyDataStore<List<Asset>>,
|
||||
private val persistenceStore: DataStore<AssetsByWalletId>,
|
||||
private val runtimeStore: StringKeyDataStore<List<Asset>>,
|
||||
) : ExpressAssetsStore {
|
||||
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId): List<Asset>? {
|
||||
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<Asset>? {
|
||||
return persistenceStore.data.firstOrNull().orEmpty()[userWalletId.stringValue]
|
||||
}
|
||||
|
||||
override suspend fun store(userWalletId: UserWalletId, item: List<Asset>) {
|
||||
dataStore.store(userWalletId.stringValue, item)
|
||||
coroutineScope {
|
||||
launch {
|
||||
runtimeStore.store(userWalletId.stringValue, item)
|
||||
}
|
||||
launch {
|
||||
persistenceStore.updateData {
|
||||
it.toMutableMap().apply {
|
||||
put(userWalletId.stringValue, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue