Updated on 2026-08-14

This commit is contained in:
Tangem 2022-04-18 22:26:51 +03:00
parent 268b74cb0e
commit 704315ddaf
18 changed files with 169 additions and 103 deletions

View file

@ -1,8 +1,8 @@
package com.tangem.tap.common.extensions
import com.tangem.common.extensions.isZero
import com.tangem.network.api.tangemTech.Coins
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.network.coinmarketcap.FiatCurrency
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
@ -10,7 +10,7 @@ import java.text.DecimalFormatSymbols
import java.util.*
fun BigDecimal.toFormattedString(
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US
): String {
val symbols = DecimalFormatSymbols(locale)
val df = DecimalFormat()
@ -26,7 +26,7 @@ fun BigDecimal.toFormattedCurrencyString(
decimals: Int, currency: String, roundingMode: RoundingMode = RoundingMode.DOWN,
limitNumberOfDecimals: Boolean = true
): String {
val decimalsForRounding = if (limitNumberOfDecimals){
val decimalsForRounding = if (limitNumberOfDecimals) {
if (decimals > 8) 8 else decimals
} else {
decimals
@ -52,7 +52,7 @@ fun BigDecimal.toFormattedFiatValue(fiatCurrencyName: FiatCurrencyName): String
return "≈ ${fiatCurrencyName} $this"
}
fun FiatCurrency.toFormattedString(): String = "${this.name} (${this.symbol}) - ${this.sign}"
fun Coins.CurrenciesResponse.Currency.toFormattedString(): String = "${this.name} (${this.code}) - ${this.unit}"
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()

View file

@ -2,6 +2,7 @@ package com.tangem.tap.common.redux
import com.tangem.domain.redux.DomainState
import com.tangem.domain.redux.domainStore
import com.tangem.domain.redux.global.NetworkServices
import com.tangem.tap.common.redux.global.GlobalMiddleware
import com.tangem.tap.common.redux.global.GlobalState
import com.tangem.tap.common.redux.navigation.NavigationState
@ -54,6 +55,9 @@ data class AppState(
val domainState: DomainState
get() = domainStore.state
val domainNetworks: NetworkServices
get() = domainState.globalState.networkServices
companion object {
fun getMiddleware(): List<Middleware<AppState>> {
return listOf(

View file

@ -10,7 +10,6 @@ import com.tangem.tap.domain.configurable.config.ConfigManager
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.features.feedback.FeedbackManager
import com.tangem.tap.features.onboarding.OnboardingManager
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import org.rekotlin.StateType
@ -20,7 +19,6 @@ data class GlobalState(
val cardVerifiedOnline: Boolean = false,
val tapWalletManager: TapWalletManager = TapWalletManager(),
val payIdManager: PayIdManager = PayIdManager(),
val coinMarketCapService: CoinMarketCapService = CoinMarketCapService(),
val configManager: ConfigManager? = null,
val warningManager: WarningMessagesManager? = null,
val feedbackManager: FeedbackManager? = null,

View file

@ -2,13 +2,17 @@ package com.tangem.tap.domain
import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.*
import com.tangem.common.extensions.guard
import com.tangem.common.services.Result
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.network.api.tangemTech.TangemTechService
import com.tangem.tap.common.ThrottlerWithValues
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.safeUpdate
import com.tangem.tap.common.extensions.stripZeroPlainString
@ -26,7 +30,6 @@ import com.tangem.tap.features.wallet.models.getPendingTransactions
import com.tangem.tap.features.wallet.redux.Currency
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.network.NetworkConnectivity
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
import com.tangem.tap.store
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -37,7 +40,9 @@ class TapWalletManager {
val walletManagerFactory: WalletManagerFactory
by lazy { WalletManagerFactory(blockchainSdkConfig) }
private val coinMarketCapService = CoinMarketCapService()
private val tangemTechService: TangemTechService
get() = store.state.domainNetworks.tangemTechService
private val blockchainSdkConfig by lazy {
store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig()
}
@ -98,20 +103,58 @@ class TapWalletManager {
}
suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currencies: List<Currency>) {
suspend fun handleFiatRatesResult(rates: Map<Currency, Result<BigDecimal>?>) {
rates.forEach { (currency, priceResult) ->
when (priceResult) {
is Result.Success -> {
dispatchOnMain(
WalletAction.LoadFiatRate.Success(
currency to priceResult.data
))
}
is Result.Failure -> dispatchOnMain(WalletAction.LoadFiatRate.Failure)
null -> {}
}
}
}
// get and submit previous result of equivalents.
val throttledResult = currencies.filter { fiatRatesThrottler.isStillThrottled(it) }.map {
Pair(it, fiatRatesThrottler.geValue(it))
}
if (throttledResult.isNotEmpty()) handleFiatRatesResult(throttledResult)
if (throttledResult.isNotEmpty()) {
handleFiatRatesResult(throttledResult.toMap())
}
val toUpdate = currencies.filter { !fiatRatesThrottler.isStillThrottled(it) }
toUpdate.forEach {
val result = coinMarketCapService.getRate(it.currencySymbol, fiatCurrency)
if (result is Result.Success) {
fiatRatesThrottler.updateThrottlingTo(it)
fiatRatesThrottler.setValue(it, result)
val toUpdateCurrencies = currencies.filter { !fiatRatesThrottler.isStillThrottled(it) }
val toUpdateIds = toUpdateCurrencies.mapNotNull { it.id }.distinct()
if (toUpdateIds.isEmpty()) return
//TODO: refactoring: move fiatRatesThrottler to the TangemTechRepository
when (val result = tangemTechService.coins.prices(fiatCurrency, toUpdateIds)) {
is Result.Success -> {
val missedCurrencies = mutableListOf<String>()
val updatedCurrencies = mutableMapOf<Currency, Result<BigDecimal>?>()
result.data.prices.forEach { (name, value) ->
val currency = toUpdateCurrencies.firstOrNull { it.id == name }.guard {
missedCurrencies.add(name)
return@forEach
}
val priceResult = Result.Success(value.toBigDecimal())
updatedCurrencies[currency] = priceResult
fiatRatesThrottler.updateThrottlingTo(currency)
fiatRatesThrottler.setValue(currency, priceResult)
}
if (missedCurrencies.isNotEmpty()) {
val missedNames = missedCurrencies.joinToString(", ")
store.dispatchDebugErrorNotification("Not found currencies to update: [$missedNames]")
}
handleFiatRatesResult(updatedCurrencies)
}
handleFiatRatesResult(listOf(it to result))
is Result.Failure -> dispatchOnMain(WalletAction.LoadFiatRate.Failure)
}
}
@ -318,21 +361,14 @@ class TapWalletManager {
is com.tangem.blockchain.extensions.Result.Failure -> {}
}
}
private suspend fun handleFiatRatesResult(results: List<Pair<Currency, Result<BigDecimal>?>>) {
results.map {
when (it.second) {
is Result.Success -> {
val rate = it.first to (it.second as Result.Success<BigDecimal>).data
dispatchOnMain(WalletAction.LoadFiatRate.Success(rate))
}
is Result.Failure -> dispatchOnMain(WalletAction.LoadFiatRate.Failure)
null -> {}
}
}
}
}
fun Wallet.getFirstToken(): Token? {
return getTokens().toList().getOrNull(0)
}
}
val Currency.id: String?
get() = when (this) {
is Currency.Blockchain -> blockchain.toNetworkId()
is Currency.Token -> token.id
}

View file

@ -4,11 +4,12 @@ import com.tangem.blockchain.common.Wallet
import com.tangem.common.card.Card
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TwinCardNumber
import com.tangem.network.api.tangemTech.Coins
import com.tangem.network.api.tangemTech.TangemTechService
import com.tangem.operations.pins.CheckUserCodesResponse
import com.tangem.tap.common.redux.NotificationAction
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.domain.termsOfUse.CardTou
import com.tangem.tap.network.coinmarketcap.FiatCurrency
import com.tangem.wallet.R
import org.rekotlin.Action
@ -20,6 +21,7 @@ sealed class DetailsAction : Action {
val cardTou: CardTou,
val fiatCurrencyName: FiatCurrencyName,
val fiatCurrencies: List<FiatCurrencyName>? = null,
val tangemTechService: TangemTechService,
) : DetailsAction()
object ShowDisclaimer : DetailsAction()
@ -46,7 +48,7 @@ sealed class DetailsAction : Action {
object CreateBackup : DetailsAction()
sealed class AppCurrencyAction : DetailsAction() {
data class SetCurrencies(val currencies: List<FiatCurrency>) : AppCurrencyAction()
data class SetCurrencies(val currencies: List<Coins.CurrenciesResponse.Currency>) : AppCurrencyAction()
object ChooseAppCurrency : AppCurrencyAction()
object Cancel : AppCurrencyAction()
data class SelectAppCurrency(val fiatCurrencyName: FiatCurrencyName) : AppCurrencyAction()

View file

@ -4,6 +4,7 @@ import com.tangem.common.CompletionResult
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.core.TangemSdkError
import com.tangem.common.services.Result
import com.tangem.network.api.tangemTech.Coins
import com.tangem.operations.pins.CheckUserCodesResponse
import com.tangem.tap.*
import com.tangem.tap.common.analytics.Analytics
@ -19,7 +20,6 @@ import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletM
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
import com.tangem.tap.features.wallet.models.hasSendableAmountsOrPendingTransactions
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -33,7 +33,7 @@ class DetailsMiddleware {
{ next ->
{ action ->
when (action) {
is DetailsAction.PrepareScreen -> prepareData()
is DetailsAction.PrepareScreen -> prepareData(action)
is DetailsAction.ResetToFactory -> eraseWalletMiddleware.handle(action)
is DetailsAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action)
is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action)
@ -68,23 +68,26 @@ class DetailsMiddleware {
}
}
private fun prepareData() {
private fun prepareData(action: DetailsAction.PrepareScreen) {
val fiatCurrenciesPrefStorage = preferencesStorage.fiatCurrenciesPrefStorage
val storedFiatCurrencies = fiatCurrenciesPrefStorage.restore()
if (storedFiatCurrencies.isNotEmpty()) {
store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(storedFiatCurrencies))
}
scope.launch {
val loadedCurrencies = preferencesStorage.getFiatCurrencies()
if (loadedCurrencies.isNullOrEmpty()) {
val response = CoinMarketCapService().getFiatCurrencies()
withContext(Dispatchers.Main) {
when (response) {
is Result.Success -> {
preferencesStorage.saveFiatCurrencies(response.data)
store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(response.data))
}
val tangemTechService = action.tangemTechService
when (val result = tangemTechService.coins.currencies()) {
is Result.Success -> {
val fiatCurrencies = result.data.currencies.filter {
it.type == Coins.CurrenciesResponse.CurrencyType.Fiat.type
}
if (fiatCurrencies.isNotEmpty() && fiatCurrencies.toSet() != storedFiatCurrencies.toSet()) {
fiatCurrenciesPrefStorage.save(fiatCurrencies)
dispatchOnMain(DetailsAction.AppCurrencyAction.SetCurrencies(fiatCurrencies))
}
}
} else {
withContext(Dispatchers.Main) {
store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(loadedCurrencies))
}
is Result.Failure -> {}
}
}
}

View file

@ -43,13 +43,15 @@ private fun handlePrepareScreen(
action: DetailsAction.PrepareScreen,
state: DetailsState,
): DetailsState {
val backupIsActive = action.scanResponse.card.backupStatus?.isActive ?: false
return DetailsState(
scanResponse = action.scanResponse,
wallets = action.wallets,
cardInfo = action.scanResponse.card.toCardInfo(),
appCurrencyState = AppCurrencyState(action.fiatCurrencyName),
appCurrencyState = state.appCurrencyState.copy(
fiatCurrencyName = action.fiatCurrencyName,
showAppCurrencyDialog = false,
),
cardTermsOfUseUrl = action.cardTou.getUrl(action.scanResponse.card),
createBackupAllowed = action.scanResponse.card.backupStatus == Card.BackupStatus.NoBackup,
)

View file

@ -3,11 +3,11 @@ package com.tangem.tap.features.details.redux
import android.net.Uri
import com.tangem.blockchain.common.Wallet
import com.tangem.domain.common.ScanResponse
import com.tangem.network.api.tangemTech.Coins
import com.tangem.tap.common.entities.Button
import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
import com.tangem.tap.network.coinmarketcap.FiatCurrency
import com.tangem.tap.store
import org.rekotlin.StateType
import java.util.*
@ -51,8 +51,9 @@ data class SecurityScreenState(
)
enum class SecurityOption { LongTap, PassCode, AccessCode }
data class AppCurrencyState(
val fiatCurrencyName: FiatCurrencyName = DEFAULT_FIAT_CURRENCY,
val showAppCurrencyDialog: Boolean = false,
val fiatCurrencies: List<FiatCurrency>? = null,
val fiatCurrencies: List<Coins.CurrenciesResponse.Currency>? = null,
)

View file

@ -2,10 +2,10 @@ package com.tangem.tap.features.details.ui
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.tangem.network.api.tangemTech.Coins
import com.tangem.tap.common.extensions.toFormattedString
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.network.coinmarketcap.FiatCurrency
import com.tangem.tap.store
import com.tangem.wallet.R
@ -13,11 +13,11 @@ class CurrencySelectionDialog {
var dialog: AlertDialog? = null
fun show(currencies: List<FiatCurrency>, currentAppCurrency: FiatCurrencyName, context: Context) {
fun show(currencies: List<Coins.CurrenciesResponse.Currency>, currentAppCurrency: FiatCurrencyName, context: Context) {
if (dialog == null) {
val currenciesToShow = currencies.map { it.toFormattedString() }.toTypedArray()
var currentSelection = currencies.indexOfFirst { it.symbol == currentAppCurrency }
var currentSelection = currencies.indexOfFirst { it.code == currentAppCurrency }
dialog = AlertDialog.Builder(context)
.setTitle(context.getString(R.string.details_row_title_currency))
@ -26,7 +26,7 @@ class CurrencySelectionDialog {
}
.setPositiveButton(context.getString(R.string.common_done)) { _, _ ->
val selectedCurrency = currencies[currentSelection]
store.dispatch(DetailsAction.AppCurrencyAction.SelectAppCurrency(selectedCurrency.symbol))
store.dispatch(DetailsAction.AppCurrencyAction.SelectAppCurrency(selectedCurrency.code))
}
.setOnDismissListener {
store.dispatch(DetailsAction.AppCurrencyAction.Cancel)

View file

@ -166,7 +166,8 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
scanNoteResponse,
store.state.walletState.walletManagers.map { it.wallet },
CardTou(),
store.state.globalState.appCurrency
store.state.globalState.appCurrency,
tangemTechService = store.state.domainNetworks.tangemTechService
))
store.dispatch(NavigationAction.NavigateTo(AppScreen.Details))
true

View file

@ -8,6 +8,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.math.BigDecimal
//TODO: refactoring: move to the domain module and aggregate it as the alternative service for TangemTech
class CoinMarketCapService() {
private val api: CoinMarketCapApi by lazy { CoinMarketCapApi.create(getApiKey()) }

View file

@ -0,0 +1,36 @@
package com.tangem.tap.persistence
import android.content.SharedPreferences
import androidx.core.content.edit
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.network.api.tangemTech.Coins
/**
[REDACTED_AUTHOR]
*/
class FiatCurrenciesPrefStorage(
private val preferences: SharedPreferences,
private val converter: MoshiJsonConverter,
) {
private val FIAT_CURRENCIES_KEY_OLD = "fiatCurrencies"
private val FIAT_CURRENCIES_KEY = "fiatCurrencies_v2"
fun migrate() {
preferences.edit(true) {
remove(FIAT_CURRENCIES_KEY_OLD)
}
}
fun save(currencies: List<Coins.CurrenciesResponse.Currency>) {
val json: String = converter.toJson(currencies)
return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply()
}
fun restore(): List<Coins.CurrenciesResponse.Currency> {
val json = preferences.getString(FIAT_CURRENCIES_KEY, "")
val type = converter.typedList(Coins.CurrenciesResponse.Currency::class.java)
if (json.isNullOrBlank()) return emptyList()
return converter.fromJson(json, type) ?: emptyList()
}
}

View file

@ -4,13 +4,9 @@ import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.network.coinmarketcap.FiatCurrency
import java.util.*
@ -20,39 +16,24 @@ class PreferencesStorage(applicationContext: Application) {
val appRatingLaunchObserver: AppRatingLaunchObserver
val usedCardsPrefStorage: UsedCardsPrefStorage
val fiatCurrenciesPrefStorage: FiatCurrenciesPrefStorage
init {
incrementLaunchCounter()
appRatingLaunchObserver = AppRatingLaunchObserver(preferences, getCountOfLaunches())
usedCardsPrefStorage = UsedCardsPrefStorage(preferences)
usedCardsPrefStorage = UsedCardsPrefStorage(preferences, MoshiJsonConverter.INSTANCE)
usedCardsPrefStorage.migrate()
}
private val fiatCurrenciesAdapter: JsonAdapter<List<FiatCurrency>> by lazy {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val type = Types.newParameterizedType(List::class.java, FiatCurrency::class.java)
moshi.adapter(type)
fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiJsonConverter.INSTANCE)
fiatCurrenciesPrefStorage.migrate()
}
fun getAppCurrency(): FiatCurrencyName {
return preferences.getString(APP_CURRENCY_KEY, DEFAULT_FIAT_CURRENCY)
?: DEFAULT_FIAT_CURRENCY
?: DEFAULT_FIAT_CURRENCY
}
fun saveAppCurrency(fiatCurrencyName: FiatCurrencyName) {
return preferences.edit().putString(APP_CURRENCY_KEY, fiatCurrencyName).apply()
}
fun getFiatCurrencies(): List<FiatCurrency>? {
val json = preferences.getString(FIAT_CURRENCIES_KEY, "")
return if (json.isNullOrBlank()) null else fiatCurrenciesAdapter.fromJson(json) as List<FiatCurrency>
}
fun saveFiatCurrencies(currencies: List<FiatCurrency>) {
val json: String = fiatCurrenciesAdapter.toJson(currencies)
return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply()
preferences.edit { putString(APP_CURRENCY_KEY, fiatCurrencyName) }
}
fun getCountOfLaunches(): Int = preferences.getInt(APP_LAUNCH_COUNT_KEY, 1)
@ -63,7 +44,7 @@ class PreferencesStorage(applicationContext: Application) {
}
fun saveDisclaimerAccepted() {
preferences.edit().putBoolean(DISCLAIMER_ACCEPTED_KEY, true).apply()
preferences.edit { putBoolean(DISCLAIMER_ACCEPTED_KEY, true) }
}
fun wasDisclaimerAccepted(): Boolean {
@ -71,7 +52,7 @@ class PreferencesStorage(applicationContext: Application) {
}
fun saveTwinsOnboardingShown() {
preferences.edit().putBoolean(TWINS_ONBOARDING_SHOWN_KEY, true).apply()
preferences.edit { putBoolean(TWINS_ONBOARDING_SHOWN_KEY, true) }
}
fun wasTwinsOnboardingShown(): Boolean {
@ -86,7 +67,6 @@ class PreferencesStorage(applicationContext: Application) {
companion object {
private const val PREFERENCES_NAME = "tapPrefs"
private const val APP_CURRENCY_KEY = "appCurrency"
private const val FIAT_CURRENCIES_KEY = "fiatCurrencies"
private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted"
private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown"
private const val APP_LAUNCH_COUNT_KEY = "launchCount"

View file

@ -11,10 +11,9 @@ import timber.log.Timber
*/
class UsedCardsPrefStorage(
private val preferences: SharedPreferences,
private val jsonConverter: MoshiJsonConverter
) {
private val jsonConverter = MoshiJsonConverter.INSTANCE
internal fun migrate() {
val scannedIds = preferences.getString(SCANNED_CARDS_IDS_KEY, null) ?: return
@ -27,7 +26,7 @@ class UsedCardsPrefStorage(
fun scanned(cardId: String) {
val restoredList = restore()
val foundItem = findCardInfo(cardId, restoredList)?.copy(isScanned = true)
?: UsedCardInfo(cardId, true)
?: UsedCardInfo(cardId, true)
save(foundItem, restoredList)
}
@ -39,7 +38,7 @@ class UsedCardsPrefStorage(
fun activationStarted(cardId: String) {
val restoredList = restore()
val foundItem = findCardInfo(cardId, restoredList)?.copy(isActivationStarted = true)
?: UsedCardInfo(cardId, isActivationStarted = true)
?: UsedCardInfo(cardId, isActivationStarted = true)
save(foundItem, restoredList)
}
@ -55,7 +54,7 @@ class UsedCardsPrefStorage(
fun activationFinished(cardId: String) {
val restoredList = restore()
val foundItem = findCardInfo(cardId, restoredList)?.copy(isActivationStarted = false)
?: UsedCardInfo(cardId, isActivationStarted = false)
?: UsedCardInfo(cardId, isActivationStarted = false)
save(foundItem, restoredList)
}

View file

@ -8,7 +8,8 @@ import com.tangem.network.api.tangemTech.TangemTechService
[REDACTED_AUTHOR]
*/
data class DomainGlobalState(
// there is a part of mirrors from the GlobalState
// there is a part of mirrors from the GlobalState.
// It updates on GlobalAction.SaveScanNoteResponse -> DomainGlobalAction.SaveScanNoteResponse(scanResponse)
val scanResponse: ScanResponse? = null,
//
val networkServices: NetworkServices = NetworkServices(),

View file

@ -9,12 +9,7 @@ interface HttpResponse
sealed interface TangemTechResponse : HttpResponse
sealed class Coins : TangemTechResponse {
data class PricesResponse(val prices: List<Price>) : Coins() {
data class Price(
val name: String,
val price: BigDecimal,
)
}
data class PricesResponse(val prices: Map<String, Double>) : Coins()
data class CheckAddressResponse(val imageHost: String?, val tokens: List<Token>, val total: Int) : Coins() {
data class Token(
@ -51,11 +46,15 @@ sealed class Coins : TangemTechResponse {
data class CurrenciesResponse(val currencies: List<Currency>) {
data class Currency(
val id: String,
val code: String,
val code: String, // this is an uppercase id
val name: String,
val rateBTC: String,
val unit: String,
val unit: String, // $, €, ₽
val type: String,
)
enum class CurrencyType(val type: String) {
Fiat("fiat"), Crypto("crypto")
}
}
}

View file

@ -11,7 +11,7 @@ interface TangemTechApi {
@GET("coins/prices")
suspend fun coinsPrices(
@Query("currency") currency: String,
@Query("ids") ids: List<String>,
@Query("ids") ids: String,
): Coins.PricesResponse
@GET("coins/check-address")

View file

@ -34,7 +34,8 @@ class TangemTechService {
private fun createApi(): TangemTechApi {
val retrofit = createRetrofitInstance(
baseUrl = baseUrl,
interceptors = headerInterceptors.toList()
interceptors = headerInterceptors.toList(),
// logEnabled = true,
)
return retrofit.create(TangemTechApi::class.java).apply {
techRoutes.forEach { it.setApi(this) }
@ -62,7 +63,9 @@ class CoinsRoute : TangemTechRoute {
currency: String,
ids: List<String>
): Result<Coins.PricesResponse> = withContext(Dispatchers.IO) {
performRequest { api.coinsPrices(currency, ids) }
performRequest {
api.coinsPrices(currency.lowercase(), ids.joinToString(","))
}
}
suspend fun checkAddress(