Updated on 2026-08-14
This commit is contained in:
parent
59680b5305
commit
b601aea5c3
13 changed files with 172 additions and 58 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit b0985600722953fae0a93bcbbc2a83930b9e0cbe
|
||||
Subproject commit 367aa6465ec6ee7fdccce6cc7d7abeed5aad1111
|
||||
|
|
@ -146,6 +146,8 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
|
|||
blockBookRest = accessTokens.bitcoin?.blockBookRest,
|
||||
),
|
||||
algorand = GetBlockAccessToken(rest = accessTokens.algorand?.rest),
|
||||
zkSyncEra = GetBlockAccessToken(jsonRpc = accessTokens.zksync?.jsonRPC),
|
||||
polygonZkEvm = GetBlockAccessToken(jsonRpc = accessTokens.polygonZkevm?.jsonRPC),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ data class GetBlockAccessTokens(
|
|||
@Json(name = "dash") val dash: GetBlockToken?,
|
||||
@Json(name = "bitcoin") val bitcoin: GetBlockToken?,
|
||||
@Json(name = "algorand") val algorand: GetBlockToken?,
|
||||
@Json(name = "polygon-zkevm") val polygonZkevm: GetBlockToken?,
|
||||
@Json(name = "zksync") val zksync: GetBlockToken?,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ leakcanary = "2.13"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "develop-576"
|
||||
tangemBlockchainSdk = "develop-593"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-339"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
|
|
@ -1,32 +1,45 @@
|
|||
package com.tangem.blockchainsdk
|
||||
|
||||
import com.tangem.blockchain.common.AccountCreator
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.WalletManagerFactory
|
||||
import com.tangem.blockchain.common.datastorage.BlockchainDataStorage
|
||||
import com.tangem.blockchain.common.logging.BlockchainSDKLogger
|
||||
import com.tangem.blockchainsdk.config.ConfigStorage
|
||||
import com.tangem.blockchain.common.network.providers.ProviderType
|
||||
import com.tangem.blockchainsdk.converters.BlockchainProviderTypesConverter
|
||||
import com.tangem.blockchainsdk.converters.BlockchainSDKConfigConverter
|
||||
import com.tangem.blockchainsdk.storage.RuntimeStore
|
||||
import com.tangem.datasource.asset.loader.AssetLoader
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
import com.tangem.datasource.config.models.ProviderModel
|
||||
import com.tangem.libs.blockchain_sdk.BuildConfig
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal typealias BlockchainProvidersResponse = Map<String, List<ProviderModel>>
|
||||
internal typealias BlockchainProviderTypes = Map<Blockchain, List<ProviderType>>
|
||||
|
||||
/**
|
||||
* Implementation of Blockchain SDK components factory
|
||||
*
|
||||
* @property assetLoader asset loader
|
||||
* @property configStorage config storage
|
||||
* @property accountCreator account creator
|
||||
* @property blockchainDataStorage blockchain data storage
|
||||
* @property blockchainSDKLogger blockchain SDK logger
|
||||
* @property assetLoader asset loader
|
||||
* @property configStore blockchain sdk config store
|
||||
* @property blockchainProviderTypesStore blockchain provider types store
|
||||
* @property accountCreator account creator
|
||||
* @property blockchainDataStorage blockchain data storage
|
||||
* @property blockchainSDKLogger blockchain SDK logger
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultBlockchainSDKFactory(
|
||||
private val assetLoader: AssetLoader,
|
||||
private val configStorage: ConfigStorage,
|
||||
private val configStore: RuntimeStore<BlockchainSdkConfig>,
|
||||
private val blockchainProviderTypesStore: RuntimeStore<BlockchainProviderTypes>,
|
||||
private val accountCreator: AccountCreator,
|
||||
private val blockchainDataStorage: BlockchainDataStorage,
|
||||
private val blockchainSDKLogger: BlockchainSDKLogger,
|
||||
|
|
@ -35,19 +48,22 @@ internal class DefaultBlockchainSDKFactory(
|
|||
override val walletManagerFactory: Flow<WalletManagerFactory> by lazy(::createWalletManagerFactory)
|
||||
|
||||
override suspend fun init() {
|
||||
val configValueModel = assetLoader.load<ConfigValueModel>(CONFIG_FILE_NAME) ?: return
|
||||
|
||||
configStorage.store(
|
||||
config = BlockchainSDKConfigConverter.convert(value = configValueModel),
|
||||
)
|
||||
coroutineScope {
|
||||
updateBlockchainSDKConfig()
|
||||
updateBlockchainProviderTypes()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getWalletManagerFactorySync(): WalletManagerFactory? = walletManagerFactory.firstOrNull()
|
||||
|
||||
private fun createWalletManagerFactory(): Flow<WalletManagerFactory> {
|
||||
return configStorage.get().map { config ->
|
||||
return combine(
|
||||
flow = configStore.get(),
|
||||
flow2 = blockchainProviderTypesStore.get(),
|
||||
) { config, blockchainProviderTypes ->
|
||||
WalletManagerFactory(
|
||||
config = config,
|
||||
blockchainProviderTypes = blockchainProviderTypes,
|
||||
accountCreator = accountCreator,
|
||||
blockchainDataStorage = blockchainDataStorage,
|
||||
loggers = listOf(blockchainSDKLogger),
|
||||
|
|
@ -55,8 +71,29 @@ internal class DefaultBlockchainSDKFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private fun CoroutineScope.updateBlockchainSDKConfig() {
|
||||
launch {
|
||||
val config = assetLoader.load<ConfigValueModel>(fileName = CONFIG_FILE_NAME) ?: return@launch
|
||||
|
||||
configStore.store(
|
||||
value = BlockchainSDKConfigConverter.convert(value = config),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.updateBlockchainProviderTypes() {
|
||||
launch {
|
||||
val providerTypes = assetLoader.load<BlockchainProvidersResponse>(fileName = PROVIDER_TYPES_FILE_NAME)
|
||||
?: return@launch
|
||||
|
||||
blockchainProviderTypesStore.store(
|
||||
value = BlockchainProviderTypesConverter.convert(providerTypes),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val CONFIG_FILE_NAME = "tangem-app-config/config_${BuildConfig.ENVIRONMENT}"
|
||||
const val PROVIDER_TYPES_FILE_NAME = "tangem-app-config/providers_order"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.tangem.blockchainsdk.config
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Storage for [BlockchainSdkConfig]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface ConfigStorage {
|
||||
|
||||
/** Get flow of [BlockchainSdkConfig] */
|
||||
fun get(): Flow<BlockchainSdkConfig>
|
||||
|
||||
/** Store [BlockchainSdkConfig] */
|
||||
suspend fun store(config: BlockchainSdkConfig)
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package com.tangem.blockchainsdk.config
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
/**
|
||||
* Runtime storage for [BlockchainSdkConfig]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class RuntimeConfigStorage : ConfigStorage {
|
||||
|
||||
private val configFlow = MutableStateFlow(value = BlockchainSdkConfig())
|
||||
|
||||
override fun get(): Flow<BlockchainSdkConfig> = configFlow
|
||||
|
||||
override suspend fun store(config: BlockchainSdkConfig) {
|
||||
configFlow.value = config
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.tangem.blockchainsdk.converters
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.network.providers.ProviderType
|
||||
import com.tangem.blockchainsdk.BlockchainProviderTypes
|
||||
import com.tangem.blockchainsdk.BlockchainProvidersResponse
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.datasource.config.models.ProviderModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Converts [BlockchainProvidersResponse] to [BlockchainProviderTypes]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal object BlockchainProviderTypesConverter :
|
||||
Converter<BlockchainProvidersResponse, BlockchainProviderTypes> {
|
||||
|
||||
override fun convert(value: BlockchainProvidersResponse): BlockchainProviderTypes {
|
||||
return value.mapNotNull { (networkId, blockchainProviders) ->
|
||||
val blockchain = Blockchain.fromNetworkId(networkId) ?: return@mapNotNull null
|
||||
|
||||
val providerTypes = blockchainProviders.mapNotNull { provider ->
|
||||
when (provider) {
|
||||
is ProviderModel.Public -> ProviderType.Public(url = provider.url)
|
||||
is ProviderModel.Private -> createPrivateProviderType(blockchain = blockchain, name = provider.name)
|
||||
ProviderModel.UnsupportedType -> {
|
||||
Timber.e("$blockchain provider type is not supported")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockchain to providerTypes
|
||||
}
|
||||
.toMap()
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun createPrivateProviderType(blockchain: Blockchain, name: String): ProviderType? {
|
||||
return when (name) {
|
||||
"blockchair" -> ProviderType.BitcoinLike.Blockchair
|
||||
"blockcypher" -> ProviderType.BitcoinLike.Blockcypher
|
||||
"adalite" -> ProviderType.Cardano.Adalite
|
||||
"tangemRosetta" -> ProviderType.Cardano.Rosetta
|
||||
"fireAcademy" -> ProviderType.Chia.FireAcademy
|
||||
"tangemChia" -> ProviderType.Chia.Tangem
|
||||
"infura" -> ProviderType.EthereumLike.Infura
|
||||
"getblock" -> ProviderType.GetBlock
|
||||
"arkhiaHedera" -> ProviderType.Hedera.Arkhia
|
||||
"kaspa" -> ProviderType.Kaspa.SecondaryAPI
|
||||
"nownodes" -> ProviderType.NowNodes
|
||||
"quicknode" -> ProviderType.QuickNode
|
||||
"solana" -> ProviderType.Solana.Official
|
||||
"ton" -> ProviderType.Ton.TonCentral
|
||||
"tron" -> ProviderType.Tron.TronGrid
|
||||
else -> {
|
||||
Timber.e("$blockchain private provider ($name) is not supported")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +77,8 @@ internal object BlockchainSDKConfigConverter : Converter<ConfigValueModel, Block
|
|||
blockBookRest = accessTokens.bitcoin?.blockBookRest,
|
||||
),
|
||||
algorand = GetBlockAccessToken(rest = accessTokens.algorand?.rest),
|
||||
zkSyncEra = GetBlockAccessToken(jsonRpc = accessTokens.zksync?.jsonRPC),
|
||||
polygonZkEvm = GetBlockAccessToken(jsonRpc = accessTokens.polygonZkevm?.jsonRPC),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package com.tangem.blockchainsdk.di
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.logging.BlockchainSDKLogger
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.DefaultBlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.accountcreator.DefaultAccountCreator
|
||||
import com.tangem.blockchainsdk.config.RuntimeConfigStorage
|
||||
import com.tangem.blockchainsdk.datastorage.DefaultBlockchainDataStorage
|
||||
import com.tangem.blockchainsdk.storage.DefaultRuntimeStore
|
||||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.asset.loader.AssetLoader
|
||||
|
|
@ -31,7 +32,8 @@ internal object BlockchainSDKFactoryModule {
|
|||
): BlockchainSDKFactory {
|
||||
return DefaultBlockchainSDKFactory(
|
||||
assetLoader = assetLoader,
|
||||
configStorage = RuntimeConfigStorage(),
|
||||
configStore = DefaultRuntimeStore(defaultValue = BlockchainSdkConfig()),
|
||||
blockchainProviderTypesStore = DefaultRuntimeStore(defaultValue = emptyMap()),
|
||||
accountCreator = DefaultAccountCreator(authProvider, tangemTechApi),
|
||||
blockchainDataStorage = DefaultBlockchainDataStorage(appPreferencesStore),
|
||||
blockchainSDKLogger = blockchainSDKLogger,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.blockchainsdk.storage
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* Default implementation of RuntimeStore
|
||||
*
|
||||
* @param defaultValue default value
|
||||
*/
|
||||
internal class DefaultRuntimeStore<T>(defaultValue: T) : RuntimeStore<T> {
|
||||
|
||||
private val flow = MutableStateFlow(value = defaultValue)
|
||||
|
||||
override fun get(): StateFlow<T> = flow
|
||||
|
||||
override suspend fun store(value: T) {
|
||||
flow.value = value
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.blockchainsdk.storage
|
||||
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* Runtime store
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface RuntimeStore<T> {
|
||||
|
||||
/** Get flow of elements [T] */
|
||||
fun get(): StateFlow<T>
|
||||
|
||||
/** Store [value] */
|
||||
suspend fun store(value: T)
|
||||
}
|
||||
|
|
@ -114,6 +114,8 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? {
|
|||
"taraxa/test" -> Blockchain.TaraxaTestnet
|
||||
"base" -> Blockchain.Base
|
||||
"base/test" -> Blockchain.BaseTestnet
|
||||
"koinos" -> Blockchain.Koinos
|
||||
"koinos/test" -> Blockchain.KoinosTestnet
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
@ -229,6 +231,8 @@ fun Blockchain.toNetworkId(): String {
|
|||
Blockchain.TaraxaTestnet -> "taraxa/test"
|
||||
Blockchain.Base -> "base"
|
||||
Blockchain.BaseTestnet -> "base/test"
|
||||
Blockchain.Koinos -> "koinos"
|
||||
Blockchain.KoinosTestnet -> "koinos/test"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,6 +306,7 @@ fun Blockchain.toCoinId(): String {
|
|||
Blockchain.Flare, Blockchain.FlareTestnet -> "flare-networks"
|
||||
Blockchain.Taraxa, Blockchain.TaraxaTestnet -> "taraxa"
|
||||
Blockchain.Base, Blockchain.BaseTestnet -> "base"
|
||||
Blockchain.Koinos, Blockchain.KoinosTestnet -> "koinos"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -332,4 +337,6 @@ private val excludedBlockchains = listOf(
|
|||
Blockchain.Nexa,
|
||||
Blockchain.NexaTestnet,
|
||||
Blockchain.Radiant,
|
||||
Blockchain.Koinos,
|
||||
Blockchain.KoinosTestnet,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue