Updated on 2026-08-14
This commit is contained in:
parent
0e1d6547d1
commit
79d823b94f
32 changed files with 156 additions and 110 deletions
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.datasource.config
|
||||
|
||||
import com.tangem.datasource.config.models.Config
|
||||
import com.tangem.datasource.config.models.ConfigModel
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ConfigManager {
|
||||
|
||||
val config: Config
|
||||
|
||||
fun load(configLoader: Loader<ConfigModel>, onComplete: ((config: Config) -> Unit)? = null)
|
||||
|
||||
fun turnOff(name: String)
|
||||
|
||||
fun resetToDefault(name: String)
|
||||
|
||||
companion object {
|
||||
const val IS_SENDING_TO_PAY_ID_ENABLED = "isSendingToPayIdEnabled"
|
||||
const val IS_CREATING_TWIN_CARDS_ALLOWED = "isCreatingTwinCardsAllowed"
|
||||
const val IS_TOP_UP_ENABLED = "isTopUpEnabled"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package com.tangem.datasource.config
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.BlockchairCredentials
|
||||
import com.tangem.blockchain.common.QuickNodeCredentials
|
||||
import com.tangem.datasource.config.ConfigManager.Companion.IS_CREATING_TWIN_CARDS_ALLOWED
|
||||
import com.tangem.datasource.config.ConfigManager.Companion.IS_SENDING_TO_PAY_ID_ENABLED
|
||||
import com.tangem.datasource.config.ConfigManager.Companion.IS_TOP_UP_ENABLED
|
||||
import com.tangem.datasource.config.models.Config
|
||||
import com.tangem.datasource.config.models.ConfigModel
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
import com.tangem.datasource.config.models.FeatureModel
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
|
||||
|
||||
override var config: Config = Config()
|
||||
private set
|
||||
|
||||
private var defaultConfig = Config()
|
||||
|
||||
override fun load(configLoader: Loader<ConfigModel>, onComplete: ((config: Config) -> Unit)?) {
|
||||
configLoader.load { configModel ->
|
||||
setupFeature(configModel.features)
|
||||
setupConfigValues(configModel.configValues)
|
||||
onComplete?.invoke(config)
|
||||
}
|
||||
}
|
||||
|
||||
override fun turnOff(name: String) {
|
||||
when (name) {
|
||||
IS_SENDING_TO_PAY_ID_ENABLED -> config = config.copy(isSendingToPayIdEnabled = false)
|
||||
IS_TOP_UP_ENABLED -> config = config.copy(isTopUpEnabled = false)
|
||||
IS_CREATING_TWIN_CARDS_ALLOWED -> config = config.copy(isCreatingTwinCardsAllowed = false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetToDefault(name: String) {
|
||||
when (name) {
|
||||
IS_SENDING_TO_PAY_ID_ENABLED -> config =
|
||||
config.copy(isSendingToPayIdEnabled = defaultConfig.isSendingToPayIdEnabled)
|
||||
IS_TOP_UP_ENABLED -> config = config.copy(isTopUpEnabled = defaultConfig.isTopUpEnabled)
|
||||
IS_CREATING_TWIN_CARDS_ALLOWED -> config =
|
||||
config.copy(isCreatingTwinCardsAllowed = defaultConfig.isCreatingTwinCardsAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFeature(featureModel: FeatureModel?) {
|
||||
val model = featureModel ?: return
|
||||
|
||||
config = config.copy(
|
||||
isTopUpEnabled = model.isTopUpEnabled,
|
||||
isSendingToPayIdEnabled = model.isSendingToPayIdEnabled,
|
||||
isCreatingTwinCardsAllowed = model.isCreatingTwinCardsAllowed,
|
||||
)
|
||||
defaultConfig = defaultConfig.copy(
|
||||
isTopUpEnabled = model.isTopUpEnabled,
|
||||
isSendingToPayIdEnabled = model.isSendingToPayIdEnabled,
|
||||
isCreatingTwinCardsAllowed = model.isCreatingTwinCardsAllowed,
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupConfigValues(configValues: ConfigValueModel?) {
|
||||
val values = configValues ?: return
|
||||
|
||||
config = createConfig(config, values)
|
||||
defaultConfig = config.copy()
|
||||
}
|
||||
|
||||
private fun createConfig(config: Config, configValues: ConfigValueModel): Config {
|
||||
return config.copy(
|
||||
coinMarketCapKey = configValues.coinMarketCapKey,
|
||||
moonPayApiKey = configValues.moonPayApiKey,
|
||||
moonPayApiSecretKey = configValues.moonPayApiSecretKey,
|
||||
mercuryoWidgetId = configValues.mercuryoWidgetId,
|
||||
mercuryoSecret = configValues.mercuryoSecret,
|
||||
blockchainSdkConfig = BlockchainSdkConfig(
|
||||
blockchairCredentials = BlockchairCredentials(
|
||||
apiKey = configValues.blockchairApiKeys,
|
||||
authToken = configValues.blockchairAuthorizationToken,
|
||||
),
|
||||
blockcypherTokens = configValues.blockcypherTokens,
|
||||
quickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = configValues.quiknodeApiKey,
|
||||
subdomain = configValues.quiknodeSubdomain,
|
||||
),
|
||||
bscQuickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = configValues.bscQuiknodeApiKey,
|
||||
subdomain = configValues.bscQuiknodeSubdomain,
|
||||
),
|
||||
infuraProjectId = configValues.infuraProjectId,
|
||||
tronGridApiKey = configValues.tronGridApiKey,
|
||||
saltPayAuthToken = configValues.saltPay.credentials.token,
|
||||
),
|
||||
appsFlyerDevKey = configValues.appsFlyer.appsFlyerDevKey,
|
||||
amplitudeApiKey = configValues.amplitudeApiKey,
|
||||
shopify = configValues.shopifyShop,
|
||||
zendesk = configValues.zendesk,
|
||||
saltPayConfig = configValues.saltPay,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.datasource.config
|
||||
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.config.models.ConfigModel
|
||||
import com.tangem.datasource.config.models.ConfigValueModel
|
||||
import com.tangem.datasource.config.models.FeatureModel
|
||||
import com.tangem.datasource.utils.AssetReader
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class FeaturesLocalLoader(
|
||||
private val assetReader: AssetReader,
|
||||
private val moshi: Moshi,
|
||||
buildEnvironment: String,
|
||||
) : Loader<ConfigModel> {
|
||||
|
||||
private val featuresName = "features_$buildEnvironment"
|
||||
private val configValuesName = "tangem-app-config/config_$buildEnvironment"
|
||||
|
||||
override fun load(onComplete: (ConfigModel) -> Unit) {
|
||||
val config = try {
|
||||
val featureAdapter: JsonAdapter<FeatureModel> = moshi.adapter(FeatureModel::class.java)
|
||||
val valuesAdapter: JsonAdapter<ConfigValueModel> = moshi.adapter(ConfigValueModel::class.java)
|
||||
|
||||
val jsonFeatures = assetReader.readAssetAsString(featuresName)
|
||||
val jsonConfigValues = assetReader.readAssetAsString(configValuesName)
|
||||
|
||||
ConfigModel(featureAdapter.fromJson(jsonFeatures), valuesAdapter.fromJson(jsonConfigValues))
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
ConfigModel.empty()
|
||||
}
|
||||
onComplete(config)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.datasource.config
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Loader<T> {
|
||||
fun load(onComplete: (T) -> Unit)
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.datasource.config.models
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
|
||||
data class Config(
|
||||
val coinMarketCapKey: String = "f6622117-c043-47a0-8975-9d673ce484de",
|
||||
val moonPayApiKey: String = "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE",
|
||||
val moonPayApiSecretKey: String = "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C",
|
||||
val mercuryoWidgetId: String = "",
|
||||
val mercuryoSecret: String = "",
|
||||
val appsFlyerDevKey: String = "",
|
||||
val amplitudeApiKey: String = "",
|
||||
val blockchainSdkConfig: BlockchainSdkConfig = BlockchainSdkConfig(),
|
||||
val isSendingToPayIdEnabled: Boolean = true,
|
||||
val isTopUpEnabled: Boolean = false,
|
||||
@Deprecated("Not relevant since version 3.23")
|
||||
val isCreatingTwinCardsAllowed: Boolean = false,
|
||||
val shopify: ShopifyShop? = null,
|
||||
val zendesk: ZendeskConfig? = null,
|
||||
val saltPayConfig: SaltPayConfig? = null,
|
||||
)
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.datasource.config.models
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
||||
class FeatureModel(
|
||||
val isWalletPayIdEnabled: Boolean,
|
||||
val isTopUpEnabled: Boolean,
|
||||
val isSendingToPayIdEnabled: Boolean,
|
||||
val isCreatingTwinCardsAllowed: Boolean,
|
||||
)
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class ConfigValueModel(
|
||||
val coinMarketCapKey: String,
|
||||
val mercuryoWidgetId: String,
|
||||
val mercuryoSecret: String,
|
||||
val moonPayApiKey: String,
|
||||
val moonPayApiSecretKey: String,
|
||||
val blockchairApiKeys: List<String>,
|
||||
val blockchairAuthorizationToken: String?,
|
||||
val quiknodeSubdomain: String,
|
||||
val quiknodeApiKey: String,
|
||||
val bscQuiknodeSubdomain: String,
|
||||
val bscQuiknodeApiKey: String,
|
||||
val blockcypherTokens: Set<String>?,
|
||||
val infuraProjectId: String?,
|
||||
val appsFlyer: AppsFlyer,
|
||||
val shopifyShop: ShopifyShop?,
|
||||
val zendesk: ZendeskConfig?,
|
||||
val saltPay: SaltPayConfig,
|
||||
val tronGridApiKey: String,
|
||||
val amplitudeApiKey: String,
|
||||
)
|
||||
|
||||
data class AppsFlyer(
|
||||
val appsFlyerDevKey: String,
|
||||
val appsFlyerAppID: String,
|
||||
)
|
||||
|
||||
class ConfigModel(
|
||||
val features: FeatureModel?,
|
||||
val configValues: ConfigValueModel?,
|
||||
) {
|
||||
companion object {
|
||||
fun empty(): ConfigModel = ConfigModel(null, null)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.tangem.datasource.config.models
|
||||
|
||||
import org.spongycastle.util.encoders.Base64.toBase64String
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
data class SaltPayConfig(
|
||||
val zendesk: ZendeskConfig,
|
||||
val kycProvider: KYCProvider,
|
||||
val credentials: Credentials,
|
||||
) {
|
||||
companion object {
|
||||
fun stub(): SaltPayConfig {
|
||||
return SaltPayConfig(
|
||||
zendesk = ZendeskConfig("", "", "", "", ""),
|
||||
kycProvider = KYCProvider("", "", "", ""),
|
||||
credentials = Credentials("", ""),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class KYCProvider(
|
||||
val baseUrl: String,
|
||||
val externalIdParameterKey: String,
|
||||
val sidParameterKey: String,
|
||||
val sidValue: String,
|
||||
)
|
||||
|
||||
data class Credentials(
|
||||
val user: String,
|
||||
val password: String,
|
||||
) {
|
||||
val token: String by lazy { "Basic ${toBase64String("$user:$password".toByteArray())}" }
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.datasource.config.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ShopifyShop(
|
||||
val domain: String,
|
||||
@Json(name = "storefrontApiKeyAndroid")
|
||||
val storefrontApiKey: String,
|
||||
val merchantID: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.datasource.config.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ZendeskConfig(
|
||||
@Json(name = "zendeskApiKey")
|
||||
val apiKey: String,
|
||||
@Json(name = "zendeskAppId")
|
||||
val appId: String,
|
||||
@Json(name = "zendeskClientId")
|
||||
val clientId: String,
|
||||
@Json(name = "zendeskAccountKey")
|
||||
val accountKey: String,
|
||||
@Json(name = "zendeskUrl")
|
||||
val url: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import com.tangem.datasource.config.ConfigManager
|
||||
import com.tangem.datasource.config.ConfigManagerImpl
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface ConfigModule {
|
||||
|
||||
@Binds
|
||||
fun bindConfigManager(configManager: ConfigManagerImpl): ConfigManager
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.datasource.utils
|
||||
|
||||
import android.content.Context
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface AssetReader {
|
||||
fun readAssetAsString(name: String): String
|
||||
}
|
||||
|
||||
class AndroidAssetReader(
|
||||
private val context: Context,
|
||||
) : AssetReader {
|
||||
|
||||
override fun readAssetAsString(name: String): String {
|
||||
return context.readAssetAsString(name)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.readAssetAsString(fileName: String): String {
|
||||
return this.assets.open("$fileName.json").bufferedReader().readText()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue