Updated on 2026-08-14
This commit is contained in:
parent
a7fcb93df7
commit
500ea8e6f3
12 changed files with 305 additions and 1 deletions
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.blockchainsdk
|
||||
|
||||
import com.tangem.blockchain.common.WalletManagerFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Blockchain SDK components factory
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface BlockchainSDKFactory {
|
||||
|
||||
/** Flow of [WalletManagerFactory] */
|
||||
val walletManagerFactory: Flow<WalletManagerFactory>
|
||||
|
||||
/** Initialize components */
|
||||
suspend fun init()
|
||||
|
||||
/** Get [WalletManagerFactory] synchronously */
|
||||
suspend fun getWalletManagerFactorySync(): WalletManagerFactory?
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.blockchainsdk
|
||||
|
||||
import com.tangem.blockchain.common.AccountCreator
|
||||
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.blockchainsdk.converters.BlockchainSDKConfigConverter
|
||||
import com.tangem.blockchainsdk.loader.ConfigLoader
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
/**
|
||||
* Implementation of Blockchain SDK components factory
|
||||
*
|
||||
* @property configLoader config loader
|
||||
* @property configStorage config storage
|
||||
* @property accountCreator account creator
|
||||
* @property blockchainDataStorage blockchain data storage
|
||||
* @property blockchainSDKLogger blockchain SDK logger
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultBlockchainSDKFactory(
|
||||
private val configLoader: ConfigLoader,
|
||||
private val configStorage: ConfigStorage,
|
||||
private val accountCreator: AccountCreator,
|
||||
private val blockchainDataStorage: BlockchainDataStorage,
|
||||
private val blockchainSDKLogger: BlockchainSDKLogger,
|
||||
) : BlockchainSDKFactory {
|
||||
|
||||
override val walletManagerFactory: Flow<WalletManagerFactory> by lazy(::createWalletManagerFactory)
|
||||
|
||||
override suspend fun init() {
|
||||
val configValueModel = configLoader.load() ?: return
|
||||
|
||||
configStorage.store(
|
||||
config = BlockchainSDKConfigConverter.convert(value = configValueModel),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getWalletManagerFactorySync(): WalletManagerFactory? = walletManagerFactory.firstOrNull()
|
||||
|
||||
private fun createWalletManagerFactory(): Flow<WalletManagerFactory> {
|
||||
return configStorage.get().map { config ->
|
||||
WalletManagerFactory(
|
||||
config = config,
|
||||
accountCreator = accountCreator,
|
||||
blockchainDataStorage = blockchainDataStorage,
|
||||
loggers = listOf(blockchainSDKLogger),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
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)
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
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,83 @@
|
|||
package com.tangem.blockchainsdk.converters
|
||||
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
* Converts [ConfigValueModel] to [BlockchainSdkConfig]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal object BlockchainSDKConfigConverter : Converter<ConfigValueModel, BlockchainSdkConfig> {
|
||||
|
||||
override fun convert(value: ConfigValueModel): BlockchainSdkConfig {
|
||||
return BlockchainSdkConfig(
|
||||
blockchairCredentials = BlockchairCredentials(
|
||||
apiKey = value.blockchairApiKeys,
|
||||
authToken = value.blockchairAuthorizationToken,
|
||||
),
|
||||
blockcypherTokens = value.blockcypherTokens,
|
||||
quickNodeSolanaCredentials = QuickNodeCredentials(
|
||||
apiKey = value.quiknodeApiKey,
|
||||
subdomain = value.quiknodeSubdomain,
|
||||
),
|
||||
quickNodeBscCredentials = QuickNodeCredentials(
|
||||
apiKey = value.bscQuiknodeApiKey,
|
||||
subdomain = value.bscQuiknodeSubdomain,
|
||||
),
|
||||
infuraProjectId = value.infuraProjectId,
|
||||
tronGridApiKey = value.tronGridApiKey,
|
||||
nowNodeCredentials = NowNodeCredentials(value.nowNodesApiKey),
|
||||
getBlockCredentials = createGetBlockCredentials(value),
|
||||
kaspaSecondaryApiUrl = value.kaspaSecondaryApiUrl,
|
||||
tonCenterCredentials = TonCenterCredentials(
|
||||
mainnetApiKey = value.tonCenterKeys.mainnet,
|
||||
testnetApiKey = value.tonCenterKeys.testnet,
|
||||
),
|
||||
chiaFireAcademyApiKey = value.chiaFireAcademyApiKey,
|
||||
chiaTangemApiKey = value.chiaTangemApiKey,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createGetBlockCredentials(configValues: ConfigValueModel): GetBlockCredentials? {
|
||||
return configValues.getBlockAccessTokens?.let { accessTokens ->
|
||||
GetBlockCredentials(
|
||||
xrp = GetBlockAccessToken(jsonRpc = accessTokens.xrp?.jsonRPC),
|
||||
cardano = GetBlockAccessToken(rosetta = accessTokens.cardano?.rosetta),
|
||||
avalanche = GetBlockAccessToken(jsonRpc = accessTokens.avalanche?.jsonRPC),
|
||||
eth = GetBlockAccessToken(jsonRpc = accessTokens.eth?.jsonRPC),
|
||||
etc = GetBlockAccessToken(jsonRpc = accessTokens.etc?.jsonRPC),
|
||||
fantom = GetBlockAccessToken(jsonRpc = accessTokens.fantom?.jsonRPC),
|
||||
rsk = GetBlockAccessToken(jsonRpc = accessTokens.rsk?.jsonRPC),
|
||||
bsc = GetBlockAccessToken(jsonRpc = accessTokens.bsc?.jsonRPC),
|
||||
polygon = GetBlockAccessToken(jsonRpc = accessTokens.polygon?.jsonRPC),
|
||||
gnosis = GetBlockAccessToken(jsonRpc = accessTokens.gnosis?.jsonRPC),
|
||||
cronos = GetBlockAccessToken(jsonRpc = accessTokens.cronos?.jsonRPC),
|
||||
solana = GetBlockAccessToken(jsonRpc = accessTokens.solana?.jsonRPC),
|
||||
ton = GetBlockAccessToken(jsonRpc = accessTokens.ton?.jsonRPC),
|
||||
tron = GetBlockAccessToken(rest = accessTokens.tron?.rest),
|
||||
cosmos = GetBlockAccessToken(rest = accessTokens.cosmos?.rest),
|
||||
near = GetBlockAccessToken(jsonRpc = accessTokens.near?.jsonRPC),
|
||||
aptos = GetBlockAccessToken(rest = accessTokens.aptos?.rest),
|
||||
dogecoin = GetBlockAccessToken(
|
||||
jsonRpc = accessTokens.dogecoin?.jsonRPC,
|
||||
blockBookRest = accessTokens.dogecoin?.blockBookRest,
|
||||
),
|
||||
litecoin = GetBlockAccessToken(
|
||||
jsonRpc = accessTokens.litecoin?.jsonRPC,
|
||||
blockBookRest = accessTokens.litecoin?.blockBookRest,
|
||||
),
|
||||
dash = GetBlockAccessToken(
|
||||
jsonRpc = accessTokens.dash?.jsonRPC,
|
||||
blockBookRest = accessTokens.dash?.blockBookRest,
|
||||
),
|
||||
bitcoin = GetBlockAccessToken(
|
||||
jsonRpc = accessTokens.bitcoin?.jsonRPC,
|
||||
blockBookRest = accessTokens.bitcoin?.blockBookRest,
|
||||
),
|
||||
algorand = GetBlockAccessToken(rest = accessTokens.algorand?.rest),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.blockchainsdk.loader
|
||||
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
|
||||
/**
|
||||
* Config loader
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface ConfigLoader {
|
||||
|
||||
/** Load config [ConfigValueModel] */
|
||||
suspend fun load(): ConfigValueModel?
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.tangem.blockchainsdk.loader
|
||||
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapter
|
||||
import com.tangem.datasource.asset.AssetReader
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Local config loader
|
||||
*
|
||||
* @param buildEnvironment build environment that defines config file name
|
||||
* @param moshi moshi
|
||||
* @property assetReader asset reader
|
||||
* @property dispatchers dispatchers
|
||||
*/
|
||||
internal class LocalConfigLoader(
|
||||
buildEnvironment: String,
|
||||
moshi: Moshi,
|
||||
private val assetReader: AssetReader,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : ConfigLoader {
|
||||
|
||||
private val configFileName = "tangem-app-config/config_$buildEnvironment"
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private val adapter: JsonAdapter<ConfigValueModel> = moshi.adapter()
|
||||
|
||||
override suspend fun load(): ConfigValueModel? {
|
||||
return runCatching(dispatchers.io) {
|
||||
val json = assetReader.readJson(fileName = configFileName)
|
||||
adapter.fromJson(json)
|
||||
}
|
||||
.fold(
|
||||
onSuccess = { parsedConfig ->
|
||||
if (parsedConfig == null) Timber.e(IllegalStateException("Parsed config is null"))
|
||||
parsedConfig
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Failed to load config from assets")
|
||||
null
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue