From dfcfce392ad2f185b03cdf712e8ec701dcc75eea Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Sep 2024 17:07:45 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../response/TokenMarketChartResponse.kt | 4 ++- .../markets/DefaultMarketsTokenRepository.kt | 29 +++++++++++++++++-- .../data/markets/MarketsBatchUpdateFetcher.kt | 20 +++++++++++++ .../analytics/MarketsDataAnalyticsEvent.kt | 13 +++++++++ .../markets/converters/TokenChartConverter.kt | 16 ++++++++-- 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/markets/models/response/TokenMarketChartResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/markets/models/response/TokenMarketChartResponse.kt index fbe921d20b..ea5be79096 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/markets/models/response/TokenMarketChartResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/markets/models/response/TokenMarketChartResponse.kt @@ -6,6 +6,8 @@ import java.math.BigDecimal @JsonClass(generateAdapter = true) data class TokenMarketChartResponse( + // There is a bug in the API, it returns null values. + // We need to filter them out. @Json(name = "prices") - val prices: Map, + val prices: Map, ) \ No newline at end of file diff --git a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt index 79576d75c3..20ca3a308c 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt @@ -103,6 +103,7 @@ internal class DefaultMarketsTokenRepository( val tokenMarketsUpdateFetcher = MarketsBatchUpdateFetcher( tangemTechApi = tangemTechApi, marketsApi = marketsApi, + analyticsEventHandler = analyticsEventHandler, onApiError = { analyticsEventHandler.send(MarketsDataAnalyticsEvent.List.Error.toEvent()) }, @@ -141,7 +142,19 @@ internal class DefaultMarketsTokenRepository( response.getOrThrow() } - return TokenChartConverter.convert(interval, result) + return TokenChartConverter.convert( + interval = interval, + value = result, + + // === Analytics === + onNullPresented = { + analyticsEventHandler.send( + MarketsDataAnalyticsEvent.ChartNullValuesError( + requestPath = "coins/history", + ), + ) + }, + ) } override suspend fun getChartPreview( @@ -163,7 +176,19 @@ internal class DefaultMarketsTokenRepository( ) } - return TokenChartConverter.convert(interval, chart) + return TokenChartConverter.convert( + interval = interval, + value = chart, + + // === Analytics === + onNullPresented = { + analyticsEventHandler.send( + MarketsDataAnalyticsEvent.ChartNullValuesError( + requestPath = "coins/history_preview", + ), + ) + }, + ) } override suspend fun getTokenInfo( diff --git a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt index 18c7155b03..f1a92028fb 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt @@ -1,6 +1,8 @@ package com.tangem.data.markets +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.common.utils.retryOnError +import com.tangem.data.markets.analytics.MarketsDataAnalyticsEvent import com.tangem.data.markets.converters.TokenMarketChartsConverter import com.tangem.data.markets.converters.TokenQuotesShortConverter import com.tangem.data.markets.converters.toRequestParam @@ -22,6 +24,7 @@ import kotlinx.coroutines.launch internal class MarketsBatchUpdateFetcher( private val marketsApi: TangemTechMarketsApi, private val tangemTechApi: TangemTechApi, + private val analyticsEventHandler: AnalyticsEventHandler, private val onApiError: () -> Unit, ) : BatchUpdateFetcher, TokenMarketUpdateRequest> { @@ -52,6 +55,7 @@ internal class MarketsBatchUpdateFetcher( updateTasks.forEachIndexed { index, deferred -> launch { val res = deferred.await() + checkForNulls(res) val batchToUpdate = toUpdate[index] update { @@ -113,6 +117,22 @@ internal class MarketsBatchUpdateFetcher( ) } + private fun checkForNulls(response: TokenMarketChartListResponse) { + response.values.forEach { chart -> + chart.prices.forEach { (_, price) -> + if (price == null) { + analyticsEventHandler.send( + MarketsDataAnalyticsEvent.ChartNullValuesError( + requestPath = "coins/history_preview", + ), + ) + + return + } + } + } + } + private inline fun catchApiError(onError: () -> Unit, block: () -> T): T { return try { block() diff --git a/data/markets/src/main/java/com/tangem/data/markets/analytics/MarketsDataAnalyticsEvent.kt b/data/markets/src/main/java/com/tangem/data/markets/analytics/MarketsDataAnalyticsEvent.kt index b58f04cb33..1c131a3cd4 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/analytics/MarketsDataAnalyticsEvent.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/analytics/MarketsDataAnalyticsEvent.kt @@ -36,7 +36,20 @@ sealed interface MarketsDataAnalyticsEvent { } fun toEvent(): AnalyticsEvent = when (this) { + is ChartNullValuesError -> this is List -> this is Details -> this } + + data class ChartNullValuesError( + val requestPath: String, + ) : AnalyticsEvent( + category = "Markets / Chart", + event = "Data Error", + params = mapOf("Request path" to requestPath), + error = IllegalStateException( + "Chart data contains null values from the API", + ), + ), + MarketsDataAnalyticsEvent } \ No newline at end of file diff --git a/data/markets/src/main/java/com/tangem/data/markets/converters/TokenChartConverter.kt b/data/markets/src/main/java/com/tangem/data/markets/converters/TokenChartConverter.kt index 744e6fef48..a036ed9768 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/converters/TokenChartConverter.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/converters/TokenChartConverter.kt @@ -6,11 +6,21 @@ import com.tangem.domain.markets.TokenChart internal object TokenChartConverter { - fun convert(interval: PriceChangeInterval, value: TokenMarketChartResponse): TokenChart { + fun convert( + interval: PriceChangeInterval, + value: TokenMarketChartResponse, + onNullPresented: () -> Unit = {}, + ): TokenChart { + val points = value.prices.mapNotNull { p -> p.value?.let { p.key to it } }.toMap() + + if (points.size < points.values.size) { + onNullPresented() + } + return TokenChart( interval = interval, - priceY = value.prices.values.toList(), - timeStamps = value.prices.keys.toList(), + priceY = points.values.toList(), + timeStamps = points.keys.toList(), ) } } \ No newline at end of file