Updated on 2026-08-14
This commit is contained in:
parent
9e948f7703
commit
147625bda1
40 changed files with 254 additions and 131 deletions
|
|
@ -19,6 +19,7 @@ dependencies {
|
|||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.analytics)
|
||||
// endregion
|
||||
|
||||
// region AndroidX libraries
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.blockchainsdk.di
|
||||
|
||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersResponseMerger
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -17,4 +19,12 @@ internal object ExcludedBlockchainsModule {
|
|||
fun bindExcludedBlockchains(excludedBlockchainsManager: ExcludedBlockchainsManager): ExcludedBlockchains {
|
||||
return ExcludedBlockchains(excludedBlockchainsManager)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun bindBlockchainProvidersResponseMerger(
|
||||
analyticsExceptionHandler: AnalyticsExceptionHandler,
|
||||
): BlockchainProvidersResponseMerger {
|
||||
return BlockchainProvidersResponseMerger(analyticsExceptionHandler)
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import javax.inject.Singleton
|
|||
internal class BlockchainProvidersResponseLoader @Inject constructor(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val blockchainProvidersStorage: BlockchainProvidersStorage,
|
||||
private val blockchainProvidersResponseMerger: BlockchainProvidersResponseMerger,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ internal class BlockchainProvidersResponseLoader @Inject constructor(
|
|||
|
||||
return loadRemote().fold(
|
||||
onSuccess = { remoteResponse ->
|
||||
BlockchainProvidersResponseMerger.merge(
|
||||
blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
package com.tangem.blockchainsdk.providers
|
||||
|
||||
import androidx.core.util.PatternsCompat
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchainsdk.BlockchainProvidersResponse
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Merger of [BlockchainProvidersResponse]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal object BlockchainProvidersResponseMerger {
|
||||
|
||||
private val firebaseCrashlytics by lazy(FirebaseCrashlytics::getInstance)
|
||||
internal class BlockchainProvidersResponseMerger @Inject internal constructor(
|
||||
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
|
||||
) {
|
||||
|
||||
private val forbiddenSchemes = listOf("wss://")
|
||||
|
||||
|
|
@ -41,7 +43,7 @@ internal object BlockchainProvidersResponseMerger {
|
|||
val missingBlockchains = result.keys - remote.keys
|
||||
val blockchainsWithoutProviders = remote.filterValues { it.isEmpty() }.keys
|
||||
|
||||
recordException(missingBlockchains = missingBlockchains + blockchainsWithoutProviders)
|
||||
logException(missingBlockchains = missingBlockchains + blockchainsWithoutProviders)
|
||||
}
|
||||
|
||||
return result.guaranteeUrlsEndWithSlash()
|
||||
|
|
@ -74,15 +76,19 @@ internal object BlockchainProvidersResponseMerger {
|
|||
return PatternsCompat.WEB_URL.matcher(inputUrl).matches()
|
||||
}
|
||||
|
||||
private fun recordException(missingBlockchains: Set<String>) {
|
||||
private fun logException(missingBlockchains: Set<String>) {
|
||||
val exception = IllegalStateException(
|
||||
"Remote config does not contain required blockchains or providers information: " +
|
||||
missingBlockchains.joinToString(),
|
||||
"Remote config does not contain some blockchains or providers information",
|
||||
)
|
||||
|
||||
Timber.e(exception)
|
||||
|
||||
firebaseCrashlytics.recordException(exception)
|
||||
analyticsExceptionHandler.sendException(
|
||||
ExceptionAnalyticsEvent(
|
||||
exception = exception,
|
||||
params = mapOf("Missing blockchains" to missingBlockchains.joinToString()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.google.common.truth.Truth
|
|||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersResponseMergerTest.Companion.localResponse
|
||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersResponseMergerTest.Companion.remoteResponse
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.config.providers.BlockchainProvidersStorage
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
|
|
@ -20,10 +22,16 @@ internal class BlockchainProvidersResponseLoaderTest {
|
|||
|
||||
private val tangemTechApi = mockk<TangemTechApi>()
|
||||
private val blockchainProvidersStorage = mockk<BlockchainProvidersStorage>()
|
||||
private val analyticsExceptionHandler = object : AnalyticsExceptionHandler {
|
||||
override fun sendException(event: ExceptionAnalyticsEvent) {
|
||||
FirebaseCrashlytics.getInstance().recordException(event.exception)
|
||||
}
|
||||
}
|
||||
|
||||
private val loader = BlockchainProvidersResponseLoader(
|
||||
tangemTechApi = tangemTechApi,
|
||||
blockchainProvidersStorage = blockchainProvidersStorage,
|
||||
blockchainProvidersResponseMerger = BlockchainProvidersResponseMerger(analyticsExceptionHandler),
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package com.tangem.blockchainsdk.providers
|
|||
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.google.firebase.crashlytics.recordException
|
||||
import com.tangem.blockchainsdk.BlockchainProvidersResponse
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
import io.mockk.*
|
||||
import org.junit.Before
|
||||
|
|
@ -13,6 +16,14 @@ import org.junit.Test
|
|||
*/
|
||||
internal class BlockchainProvidersResponseMergerTest {
|
||||
|
||||
private val blockchainProvidersResponseMerger = BlockchainProvidersResponseMerger(
|
||||
object : AnalyticsExceptionHandler {
|
||||
override fun sendException(event: ExceptionAnalyticsEvent) {
|
||||
FirebaseCrashlytics.getInstance().recordException(event.exception)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(FirebaseCrashlytics::class)
|
||||
|
|
@ -25,7 +36,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
fun test_if_both_configs_are_empty() {
|
||||
val expected = emptyMap<String, List<ProviderModel>>()
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = emptyMap(),
|
||||
remote = emptyMap(),
|
||||
)
|
||||
|
|
@ -37,7 +48,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
fun test_if_local_config_is_empty() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = emptyMap(),
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
|
@ -49,7 +60,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
fun test_if_remote_config_is_empty() {
|
||||
val expected = localResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = emptyMap(),
|
||||
)
|
||||
|
|
@ -61,7 +72,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
fun test_if_both_configs_are_not_empty() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
|
@ -73,7 +84,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
fun test_if_configs_are_equal() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = remoteResponse,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
|
@ -88,7 +99,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
|
||||
val expected = localResponseWithEth + remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponseWithEth,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
|
@ -103,7 +114,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
val eth = "ethereum" to emptyList<ProviderModel>()
|
||||
val remoteWithEth = remoteResponse + eth
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
|
@ -121,7 +132,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
*/
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithoutLocal,
|
||||
)
|
||||
|
|
@ -137,7 +148,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
|
||||
val expected = remoteResponse + ("ethereum" to listOf(nowNodesProvider))
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
|
@ -152,7 +163,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
|
@ -170,7 +181,7 @@ internal class BlockchainProvidersResponseMergerTest {
|
|||
|
||||
val expected = remoteResponse + eth.addSlash() + kaspa.addSlash()
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
val actual = blockchainProvidersResponseMerger.merge(
|
||||
local = localWithKaspa,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue