Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-27 00:26:35 +08:00
parent 463e5b1d52
commit 2a61e32f0c
4 changed files with 57 additions and 11 deletions

View file

@ -32,6 +32,12 @@ dependencies {
implementation(deps.timber)
// endregion
// region Firebase libraries
implementation(platform(deps.firebase.bom))
implementation(deps.firebase.analytics)
implementation(deps.firebase.crashlytics)
// endregion
// region Tangem libraries
implementation(deps.tangem.blockchain) { exclude(module = "joda-time") }
implementation(deps.tangem.card.core)

View file

@ -1,5 +1,6 @@
package com.tangem.blockchainsdk.loader
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.blockchainsdk.BlockchainProvidersResponse
import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.api.tangemTech.TangemTechServiceApi
@ -28,18 +29,26 @@ internal class BlockchainProvidersResponseLoader @Inject constructor(
private val dispatchers: CoroutineDispatcherProvider,
) {
private val firebaseCrashlytics by lazy(FirebaseCrashlytics::getInstance)
/** Load [BlockchainProvidersResponse] */
suspend fun load(): BlockchainProvidersResponse? {
val localResponse = loadLocal() ?: return null
return runCatching(dispatcher = dispatchers.io, block = ::loadRemote)
.fold(
onSuccess = { it },
onSuccess = { remoteResponse -> mergeResponses(local = localResponse, remote = remoteResponse) },
onFailure = {
Timber.e(it, "Failed to load blockchain provider types from backend")
loadLocal()
localResponse
},
)
}
private suspend fun loadLocal(): BlockchainProvidersResponse? {
return assetLoader.load<BlockchainProvidersResponse>(fileName = PROVIDER_TYPES_FILE_NAME)
}
private suspend fun loadRemote(): BlockchainProvidersResponse {
return tangemTechServiceApi.getBlockchainProviders(
cardPublicKey = authProvider.getCardPublicKey(),
@ -47,8 +56,39 @@ internal class BlockchainProvidersResponseLoader @Inject constructor(
)
}
private suspend fun loadLocal(): BlockchainProvidersResponse? {
return assetLoader.load<BlockchainProvidersResponse>(fileName = PROVIDER_TYPES_FILE_NAME)
/** Merge blockchains with non-empty providers [remote] from remote with blockchains from local [local] */
private fun mergeResponses(
local: BlockchainProvidersResponse,
remote: BlockchainProvidersResponse,
): BlockchainProvidersResponse {
/*
* Example:
* val remote = mapOf("a" to 1, "b" to 2, "c" to 3)
* val local = mapOf("a" to 11, "e" to 4, "f" to 5)
*
* local + remote // { a = 1, e = 4, f = 5, b = 2, c = 3 }
*/
val result = local + remote.filterValues { it.isNotEmpty() }
if (result != remote) {
val missingBlockchains = result.keys - remote.keys
val blockchainsWithoutProviders = remote.filterValues { it.isEmpty() }.keys
recordException(missingBlockchains = missingBlockchains + blockchainsWithoutProviders)
}
return result
}
private fun recordException(missingBlockchains: Set<String>) {
val exception = IllegalStateException(
"Remote config does not contain required blockchains or providers information: " +
missingBlockchains.joinToString(),
)
Timber.e(exception)
firebaseCrashlytics.recordException(exception)
}
private companion object {