Updated on 2026-08-14

This commit is contained in:
Tangem 2023-08-10 12:21:28 +03:00
parent 7e992b986b
commit 3e1f52942c
41 changed files with 220 additions and 38 deletions

@ -1 +1 @@
Subproject commit 8c1c53b73950698d4acfa4d925b8c14bf6f0da63
Subproject commit fad890b2a0b552be60d124949ca0a3a4d672dac1

View file

@ -12,6 +12,7 @@ dependencies {
implementation(projects.core.utils)
implementation(projects.libs.auth)
implementation(projects.domain.core)
implementation(projects.domain.tokens.models)
implementation(projects.domain.wallets.models)
/** Tangem libraries */

View file

@ -60,4 +60,11 @@ interface TangemTechApi {
@Query(value = "locale") locale: String,
@Query(value = "shops") shops: String,
): SalesResponse
@GET("quotes")
suspend fun getQuotes(
@Query("currencyId") currencyId: String,
@Query("coinIds") coinIds: String,
@Query("fields") fields: String = "price,priceChange24h,lastUpdatedAt",
): QuotesResponse
}

View file

@ -0,0 +1,19 @@
package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json
import java.math.BigDecimal
data class QuotesResponse(
@Json(name = "quotes")
val quotes: Map<String, Quote>,
) {
data class Quote(
@Json(name = "price")
val price: BigDecimal,
@Json(name = "priceChange24h")
val priceChange: BigDecimal,
@Json(name = "lastUpdatedAt")
val lastUpdated: String,
)
}

View file

@ -0,0 +1,31 @@
package com.tangem.datasource.di
import android.content.Context
import com.squareup.moshi.Moshi
import com.tangem.datasource.local.datastore.SharedPreferencesDataStore
import com.tangem.datasource.local.quote.DefaultQuotesStore
import com.tangem.datasource.local.quote.QuotesStore
import com.tangem.datasource.local.quote.model.StoredQuote
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object QuotesStoreModule {
@Provides
@Singleton
fun provideQuotesStore(@ApplicationContext context: Context, @NetworkMoshi moshi: Moshi): QuotesStore {
return DefaultQuotesStore(
dataStore = SharedPreferencesDataStore(
preferencesName = "quotes",
context = context,
adapter = moshi.adapter(StoredQuote::class.java),
),
)
}
}

View file

@ -0,0 +1,76 @@
package com.tangem.datasource.local.datastore
import android.content.Context
import android.content.Context.MODE_PRIVATE
import androidx.core.content.edit
import com.squareup.moshi.JsonAdapter
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.datasource.local.datastore.model.WriteTrigger
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.*
import timber.log.Timber
internal class SharedPreferencesDataStore<Value : Any>(
preferencesName: String,
private val context: Context,
private val adapter: JsonAdapter<Value>,
) : StringKeyDataStore<Value> {
private val sharedPreferences by lazy {
context.getSharedPreferences(preferencesName, MODE_PRIVATE)
}
private val writeTrigger = MutableSharedFlow<WriteTrigger>(
replay = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
override fun get(key: String): Flow<Value> {
return writeTrigger
.onEmpty { emit(WriteTrigger) }
.map { getInternal(key) }
.filterNotNull()
}
override suspend fun getSyncOrNull(key: String): Value? {
return getInternal(key)
}
override suspend fun store(key: String, item: Value) {
try {
val json = adapter.toJson(item)
sharedPreferences.edit { putString(key, json) }
writeTrigger.emit(WriteTrigger)
} catch (e: Throwable) {
Timber.e(e, "Unable to edit preferences: $key")
}
}
override suspend fun store(items: Map<String, Value>) {
items.forEach { (key, item) ->
store(key, item)
}
}
override suspend fun remove(key: String) {
sharedPreferences.edit {
remove(key)
}
}
override suspend fun clear() {
sharedPreferences.edit { clear() }
}
private fun getInternal(key: String): Value? {
return try {
val json = sharedPreferences.getString(key, null) ?: return null
adapter.fromJson(json)
} catch (e: Throwable) {
Timber.e(e, "Unable to get value from preferences: $key")
null
}
}
}

View file

@ -0,0 +1,26 @@
package com.tangem.datasource.local.quote
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.datasource.local.quote.model.StoredQuote
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
internal class DefaultQuotesStore(
private val dataStore: StringKeyDataStore<StoredQuote>,
) : QuotesStore {
override fun get(rawCurrenciesIds: Set<String>): Flow<Set<StoredQuote>> {
val flows = rawCurrenciesIds.map { rawCurrencyId ->
dataStore.get(rawCurrencyId)
}
return combine(flows) { quotes -> quotes.toSet() }
}
override suspend fun store(response: QuotesResponse) {
response.quotes.forEach { (rawCurrencyId, quote) ->
dataStore.store(rawCurrencyId, StoredQuote(rawCurrencyId, quote))
}
}
}

View file

@ -0,0 +1,12 @@
package com.tangem.datasource.local.quote
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
import com.tangem.datasource.local.quote.model.StoredQuote
import kotlinx.coroutines.flow.Flow
interface QuotesStore {
fun get(rawCurrenciesIds: Set<String>): Flow<Set<StoredQuote>>
suspend fun store(response: QuotesResponse)
}

View file

@ -0,0 +1,9 @@
package com.tangem.datasource.local.quote.model
import com.squareup.moshi.Json
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
data class StoredQuote(
@Json(name = "rawCurrencyId") val rawCurrencyId: String,
@Json(name = "quote") val quote: QuotesResponse.Quote,
)

View file

@ -10,7 +10,7 @@ import com.tangem.datasource.local.token.UserTokensStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.core.error.DataError
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId

View file

@ -7,8 +7,8 @@ import com.tangem.data.tokens.utils.ResponseCurrenciesFactory
import com.tangem.datasource.local.token.UserTokensStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade

View file

@ -1,7 +1,7 @@
package com.tangem.data.tokens.repository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Quote
import com.tangem.domain.tokens.repository.QuotesRepository
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow

View file

@ -6,7 +6,7 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import timber.log.Timber
import com.tangem.blockchain.common.Token as SdkToken

View file

@ -1,7 +1,7 @@
package com.tangem.data.tokens.utils
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult

View file

@ -6,7 +6,7 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import timber.log.Timber
import com.tangem.blockchain.common.Token as SdkToken

View file

@ -6,7 +6,7 @@ import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.blockchain.common.Token as SdkToken

View file

@ -2,7 +2,7 @@ package com.tangem.data.tokens.utils
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
internal class UserTokensResponseFactory {

View file

@ -11,7 +11,6 @@ dependencies {
implementation(project(":libs:auth"))
implementation(projects.domain.demo)
implementation(projects.domain.models)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.wallets.models)

View file

@ -11,7 +11,7 @@ import com.tangem.datasource.local.walletmanager.WalletManagersStore
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.util.hasDerivation
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem

View file

@ -1,6 +1,6 @@
package com.tangem.domain.walletmanager
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem

View file

@ -1,6 +1,6 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.utils.converter.Converter
import com.tangem.blockchain.common.Token as SdkToken

View file

@ -1,6 +1,4 @@
package com.tangem.domain.tokens.model
import com.tangem.domain.tokens.models.Network
package com.tangem.domain.tokens.models
/**
* Represents a generic cryptocurrency.

View file

@ -1,4 +1,4 @@
package com.tangem.domain.tokens.model
package com.tangem.domain.tokens.models
import java.math.BigDecimal

View file

@ -8,7 +8,7 @@ import arrow.core.raise.ensureNotNull
import arrow.core.toNonEmptyListOrNull
import arrow.core.toNonEmptySetOrNull
import com.tangem.domain.tokens.error.TokenListSortingError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId

View file

@ -3,8 +3,8 @@ package com.tangem.domain.tokens
import arrow.core.Either
import com.tangem.domain.tokens.error.CurrencyError
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository

View file

@ -1,5 +1,6 @@
package com.tangem.domain.tokens.model
import com.tangem.domain.tokens.models.CryptoCurrency
import java.math.BigDecimal
/**

View file

@ -1,5 +1,6 @@
package com.tangem.domain.tokens.model
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import java.math.BigDecimal

View file

@ -4,7 +4,9 @@ import arrow.core.*
import arrow.core.raise.*
import com.tangem.domain.tokens.GetTokenListUseCase
import com.tangem.domain.tokens.model.*
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.tokens.models.Quote
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository

View file

@ -1,9 +1,9 @@
package com.tangem.domain.tokens.operations
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Quote
import java.math.BigDecimal
internal class CurrencyStatusOperations(

View file

@ -1,6 +1,6 @@
package com.tangem.domain.tokens.repository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow

View file

@ -1,7 +1,7 @@
package com.tangem.domain.tokens.repository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Quote
import kotlinx.coroutines.flow.Flow
/**

View file

@ -6,7 +6,7 @@ import arrow.core.right
import com.tangem.domain.core.error.DataError
import com.tangem.domain.tokens.error.TokenListSortingError
import com.tangem.domain.tokens.mock.MockTokens
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider

View file

@ -9,10 +9,10 @@ import com.tangem.domain.tokens.mock.MockNetworks
import com.tangem.domain.tokens.mock.MockQuotes
import com.tangem.domain.tokens.mock.MockTokens
import com.tangem.domain.tokens.mock.MockTokensStates
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Quote
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
import com.tangem.domain.tokens.repository.MockNetworksRepository
import com.tangem.domain.tokens.repository.MockQuotesRepository

View file

@ -9,10 +9,10 @@ import com.tangem.domain.tokens.mock.MockNetworks
import com.tangem.domain.tokens.mock.MockQuotes
import com.tangem.domain.tokens.mock.MockTokenLists
import com.tangem.domain.tokens.mock.MockTokens
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.NetworkStatus
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.tokens.models.Quote
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
import com.tangem.domain.tokens.repository.MockNetworksRepository
import com.tangem.domain.tokens.repository.MockQuotesRepository

View file

@ -1,7 +1,7 @@
package com.tangem.domain.tokens.mock
import arrow.core.nonEmptySetOf
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.Quote
import java.math.BigDecimal
@Suppress("MemberVisibilityCanBePrivate")

View file

@ -1,6 +1,6 @@
package com.tangem.domain.tokens.mock
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
internal object MockTokens {

View file

@ -3,7 +3,7 @@ package com.tangem.domain.tokens.repository
import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.domain.core.error.DataError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

View file

@ -3,8 +3,8 @@ package com.tangem.domain.tokens.repository
import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.domain.core.error.DataError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Quote
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

View file

@ -1,6 +1,6 @@
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
internal fun getTokenItemId(currencyId: CryptoCurrency.ID): String = currencyId.value

View file

@ -2,8 +2,8 @@ package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.it
import androidx.annotation.DrawableRes
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem

View file

@ -3,8 +3,8 @@ package com.tangem.feature.wallet.presentation.wallet.utils
import androidx.annotation.DrawableRes
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.utils.converter.Converter