Updated on 2026-08-14
This commit is contained in:
parent
fcdfe622f9
commit
effaf2d680
12 changed files with 157 additions and 13 deletions
|
|
@ -79,8 +79,8 @@ class UserTokensRepository(
|
|||
private fun List<Currency>.toUserTokensResponse(): UserTokensResponse {
|
||||
return UserTokensResponse(
|
||||
tokens = CurrencyConverter.convertList(input = this),
|
||||
group = GROUP_DEFAULT_VALUE,
|
||||
sort = SORT_DEFAULT_VALUE,
|
||||
group = UserTokensResponse.GroupType.NONE,
|
||||
sort = UserTokensResponse.SortType.MANUAL,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -121,8 +121,6 @@ class UserTokensRepository(
|
|||
private fun getUserWalletId(card: CardDTO): String? = UserWalletIdBuilder.card(card).build()?.stringValue
|
||||
|
||||
companion object {
|
||||
private const val GROUP_DEFAULT_VALUE = "none"
|
||||
private const val SORT_DEFAULT_VALUE = "manual"
|
||||
private const val NOT_FOUND_HTTP_CODE = "404"
|
||||
|
||||
// TODO("After adding DI") get dependencies by DI
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.files.FileReader
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
|
||||
@Deprecated("Use [com.tangem.datasource.local.token.UserTokensStore] instead.")
|
||||
class UserTokensStorageService(private val fileReader: FileReader) {
|
||||
private val userTokensAdapter: JsonAdapter<UserTokensResponse> =
|
||||
MoshiConverter.networkMoshi.adapter(UserTokensResponse::class.java)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ plugins {
|
|||
dependencies {
|
||||
|
||||
/** Project */
|
||||
implementation(project(":core:utils"))
|
||||
implementation(project(":libs:auth"))
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.libs.auth)
|
||||
implementation(projects.domain.core)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(deps.tangem.blockchain)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import com.squareup.moshi.Json
|
|||
|
||||
data class UserTokensResponse(
|
||||
@Json(name = "version") val version: Int = 0,
|
||||
@Json(name = "group") val group: String? = null,
|
||||
@Json(name = "sort") val sort: String? = null,
|
||||
@Json(name = "group") val group: GroupType,
|
||||
@Json(name = "sort") val sort: SortType,
|
||||
@Json(name = "tokens") val tokens: List<Token> = emptyList(),
|
||||
) {
|
||||
|
||||
|
|
@ -18,4 +18,26 @@ data class UserTokensResponse(
|
|||
@Json(name = "decimals") val decimals: Int,
|
||||
@Json(name = "contractAddress") val contractAddress: String?,
|
||||
)
|
||||
|
||||
enum class GroupType {
|
||||
@Json(name = "none")
|
||||
NONE,
|
||||
|
||||
@Json(name = "token")
|
||||
TOKEN,
|
||||
|
||||
@Json(name = "network")
|
||||
NETWORK,
|
||||
}
|
||||
|
||||
enum class SortType {
|
||||
@Json(name = "balance")
|
||||
BALANCE,
|
||||
|
||||
@Json(name = "manual")
|
||||
MANUAL,
|
||||
|
||||
@Json(name = "marketcap")
|
||||
MARKETCAP,
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,8 @@ class MoshiModule {
|
|||
@NetworkMoshi
|
||||
fun provideNetworkMoshi(): Moshi {
|
||||
return Moshi.Builder()
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.add(BigDecimalAdapter())
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.files.FileReader
|
||||
import com.tangem.datasource.local.token.FileUserTokensStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object UserTokensStoreModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserTokensStore(fileReader: FileReader, @NetworkMoshi moshi: Moshi): UserTokensStore {
|
||||
return FileUserTokensStore(fileReader, moshi)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.datasource.local.cache
|
||||
|
||||
import com.tangem.datasource.local.cache.model.CacheKey
|
||||
import com.tangem.datasource.local.store.RuntimeStore
|
||||
import com.tangem.datasource.local.datastore.RuntimeDataStore
|
||||
|
||||
internal class RuntimeCacheKeysStore : CacheKeysStore {
|
||||
|
||||
private val store = RuntimeStore(keyProvider = CacheKey::id)
|
||||
private val store = RuntimeDataStore(keyProvider = CacheKey::id)
|
||||
|
||||
override fun get(id: String): CacheKey? {
|
||||
return store.getSync { it.id == id }.firstOrNull()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.datasource.local.datastore
|
||||
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.tangem.datasource.files.FileReader
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
internal class FileDataStore<Data>(
|
||||
private val fileNameProvider: (key: String) -> String,
|
||||
private val fileReader: FileReader,
|
||||
private val adapter: JsonAdapter<Data>,
|
||||
) {
|
||||
|
||||
private val writeTrigger = MutableSharedFlow<Unit>(
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
)
|
||||
|
||||
fun get(key: String): Flow<Data> {
|
||||
return writeTrigger
|
||||
.map { getInternal(fileNameProvider(key)) }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
fun getSync(key: String): Data? {
|
||||
return getInternal(fileNameProvider(key))
|
||||
}
|
||||
|
||||
fun store(key: String, content: Data) {
|
||||
try {
|
||||
val json = adapter.toJson(content)
|
||||
|
||||
fileReader.rewriteFile(json, fileNameProvider(key))
|
||||
writeTrigger.tryEmit(Unit)
|
||||
} catch (e: Throwable) {
|
||||
throw DataError.PersistenceError.UnableToWriteFile(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInternal(fileName: String): Data? {
|
||||
return try {
|
||||
val json = fileReader.readFile(fileName)
|
||||
|
||||
adapter.fromJson(json)
|
||||
} catch (e: Throwable) {
|
||||
throw DataError.PersistenceError.UnableToReadFile(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.datasource.local.store
|
||||
package com.tangem.datasource.local.datastore
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
internal class RuntimeStore<Key, Data>(private val keyProvider: (Data) -> Key) {
|
||||
internal class RuntimeDataStore<Key, Data>(private val keyProvider: (Data) -> Key) {
|
||||
|
||||
private val store = MutableStateFlow<HashMap<Key, Data>>(hashMapOf())
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.datasource.local.token
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.files.FileReader
|
||||
import com.tangem.datasource.local.datastore.FileDataStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal class FileUserTokensStore(fileReader: FileReader, moshi: Moshi) : UserTokensStore {
|
||||
|
||||
private val store = FileDataStore<UserTokensResponse>(
|
||||
fileNameProvider = { key -> "user_tokens_$key" },
|
||||
fileReader = fileReader,
|
||||
adapter = moshi.adapter(UserTokensResponse::class.java),
|
||||
)
|
||||
|
||||
override fun get(userWalletId: String): Flow<UserTokensResponse> {
|
||||
return store.get(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun getSync(userWalletId: String): UserTokensResponse? {
|
||||
return store.getSync(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun store(userWalletId: String, tokens: UserTokensResponse) {
|
||||
store.store(userWalletId, tokens)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.datasource.local.token
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserTokensStore {
|
||||
|
||||
fun get(userWalletId: String): Flow<UserTokensResponse>
|
||||
|
||||
suspend fun getSync(userWalletId: String): UserTokensResponse?
|
||||
|
||||
suspend fun store(userWalletId: String, tokens: UserTokensResponse)
|
||||
}
|
||||
|
|
@ -6,4 +6,11 @@ sealed class DataError : Exception() {
|
|||
|
||||
object NoInternetConnection : NetworkError()
|
||||
}
|
||||
|
||||
sealed class PersistenceError : DataError() {
|
||||
|
||||
data class UnableToReadFile(override val cause: Throwable) : DataError()
|
||||
|
||||
data class UnableToWriteFile(override val cause: Throwable) : DataError()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue