Updated on 2026-08-14

This commit is contained in:
Tangem 2025-02-12 11:46:40 +04:00
parent 90e783441c
commit 5ae5b86980
5 changed files with 78 additions and 39 deletions

View file

@ -12,12 +12,12 @@ data class HotCryptoResponse(
@JsonClass(generateAdapter = true)
data class Token(
@Json(name = "id") val id: String,
@Json(name = "symbol") val symbol: String,
@Json(name = "name") val name: String,
@Json(name = "network_id") val networkId: String,
@Json(name = "current_price") val currentPrice: BigDecimal,
@Json(name = "price_change_percentage_24h") val priceChangePercentage: BigDecimal,
@Json(name = "id") val id: String? = null,
@Json(name = "symbol") val symbol: String? = null,
@Json(name = "name") val name: String? = null,
@Json(name = "network_id") val networkId: String? = null,
@Json(name = "current_price") val currentPrice: BigDecimal? = null,
@Json(name = "price_change_percentage_24h") val priceChangePercentage: BigDecimal? = null,
@Json(name = "contract_address") val contractAddress: String? = null, // specific for token
@Json(name = "decimal_count") val decimalCount: Int? = null, // specific for token
)

View file

@ -35,7 +35,9 @@ internal class DefaultHotCryptoRepository(
scanResponse = userWallet.scanResponse,
imageHost = it.imageHost,
excludedBlockchains = excludedBlockchains,
).convertList(input = it.tokens)
)
.convertList(input = it.tokens)
.filterNotNull()
}
}
}

View file

@ -10,7 +10,9 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.onramp.model.HotCryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.Quote
import com.tangem.utils.converter.Converter
import java.math.BigDecimal
/**
* Converter from [HotCryptoResponse.Token] to [HotCryptoCurrency]
@ -25,44 +27,75 @@ internal class HotCryptoCurrencyConverter(
private val scanResponse: ScanResponse,
private val imageHost: String?,
private val excludedBlockchains: ExcludedBlockchains,
) : Converter<HotCryptoResponse.Token, HotCryptoCurrency> {
) : Converter<HotCryptoResponse.Token, HotCryptoCurrency?> {
private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory(excludedBlockchains) }
override fun convert(value: HotCryptoResponse.Token): HotCryptoCurrency {
val network = createNetwork(value.networkId)
override fun convert(value: HotCryptoResponse.Token): HotCryptoCurrency? {
val rawId = value.id?.let(CryptoCurrency::RawID) ?: return null
val network = value.networkId?.let(::createNetwork) ?: return null
val currency = createCryptoCurrencyOrNull(rawId, value, network) ?: return null
return HotCryptoCurrency(
cryptoCurrency = currency.setupIconUrl(id = rawId.value),
quote = createQuote(
fiatRate = value.currentPrice,
priceChange = value.priceChangePercentage,
rawCurrencyId = rawId,
),
)
}
private fun createCryptoCurrencyOrNull(
rawId: CryptoCurrency.RawID,
value: HotCryptoResponse.Token,
network: Network,
): CryptoCurrency? {
val name = value.name
val symbol = value.symbol
if (name.isNullOrBlank() || symbol.isNullOrBlank()) return null
val contractAddress = value.contractAddress
val decimals = value.decimalCount
val currency = if (contractAddress != null && decimals != null) {
return if (contractAddress != null && decimals != null) {
cryptoCurrencyFactory.createToken(
network = network,
rawId = CryptoCurrency.RawID(value.id),
name = value.name,
symbol = value.symbol,
rawId = rawId,
name = name,
symbol = symbol,
decimals = decimals,
contractAddress = contractAddress,
)
} else {
cryptoCurrencyFactory.createCoin(network = network)
}
}
return HotCryptoCurrency(
cryptoCurrency = currency.setupIconUrl(id = value.id),
fiatRate = value.currentPrice,
priceChange = value.priceChangePercentage,
private fun createNetwork(networkId: String): Network? {
return getNetwork(
blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)),
extraDerivationPath = null,
scanResponse = scanResponse,
excludedBlockchains = excludedBlockchains,
)
}
private fun createNetwork(networkId: String): Network {
return requireNotNull(
getNetwork(
blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)),
extraDerivationPath = null,
scanResponse = scanResponse,
excludedBlockchains = excludedBlockchains,
),
)
private fun createQuote(
fiatRate: BigDecimal?,
priceChange: BigDecimal?,
rawCurrencyId: CryptoCurrency.RawID,
): Quote {
return if (fiatRate != null && priceChange != null) {
Quote.Value(
rawCurrencyId = rawCurrencyId,
fiatRate = fiatRate,
priceChange = priceChange.movePointLeft(2),
)
} else {
Quote.Empty(rawCurrencyId)
}
}
private fun CryptoCurrency.setupIconUrl(id: String): CryptoCurrency {

View file

@ -1,19 +1,17 @@
package com.tangem.domain.onramp.model
import com.tangem.domain.tokens.model.CryptoCurrency
import java.math.BigDecimal
import com.tangem.domain.tokens.model.Quote
/**
* Hot crypto currency
*
* @property cryptoCurrency crypto currency
* @property fiatRate fiat rate
* @property priceChange price change
* @property quote quote
*
[REDACTED_AUTHOR]
*/
data class HotCryptoCurrency(
val cryptoCurrency: CryptoCurrency,
val fiatRate: BigDecimal,
val priceChange: BigDecimal,
val quote: Quote,
)

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.format.bigdecimal.percent
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.onramp.model.HotCryptoCurrency
import com.tangem.domain.tokens.model.Quote
import com.tangem.utils.converter.Converter
import java.math.BigDecimal
@ -29,7 +30,7 @@ internal class HotTokenItemStateConverter(
id = value.cryptoCurrency.id.value,
iconState = CryptoCurrencyToIconStateConverter().convert(value.cryptoCurrency),
titleState = TokenItemState.TitleState.Content(text = stringReference(value.cryptoCurrency.name)),
subtitleState = value.getCryptoPriceState(appCurrency),
subtitleState = value.quote.getCryptoPriceState(appCurrency),
fiatAmountState = null,
subtitle2State = null,
onItemClick = onItemClick.let { onItemClick -> { onItemClick(it, value) } },
@ -37,12 +38,17 @@ internal class HotTokenItemStateConverter(
)
}
private fun HotCryptoCurrency.getCryptoPriceState(appCurrency: AppCurrency): TokenItemState.SubtitleState {
return TokenItemState.SubtitleState.CryptoPriceContent(
price = fiatRate.getFormattedCryptoPrice(appCurrency),
priceChangePercent = priceChange.format { percent() },
type = priceChange.getPriceChangeType(),
)
private fun Quote.getCryptoPriceState(appCurrency: AppCurrency): TokenItemState.SubtitleState {
return when (this) {
is Quote.Empty -> TokenItemState.SubtitleState.Unknown
is Quote.Value -> {
TokenItemState.SubtitleState.CryptoPriceContent(
price = fiatRate.getFormattedCryptoPrice(appCurrency),
priceChangePercent = priceChange.format { percent() },
type = priceChange.getPriceChangeType(),
)
}
}
}
private fun BigDecimal.getFormattedCryptoPrice(appCurrency: AppCurrency): String {