From 4fa88e1959de70f79c5d9889b11d9bf59d0ce202 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Nov 2020 10:30:29 +0300 Subject: [PATCH] Updated on 2026-08-14 --- app/src/main/assets/dev_config_values.json | 30 ++++---- app/src/main/assets/dev_features.json | 38 +++++---- .../java/com/tangem/tap/TapApplication.kt | 11 ++- app/src/main/java/com/tangem/tap/TapConfig.kt | 9 --- .../com/tangem/tap/domain/TapWalletManager.kt | 14 ++-- .../com/tangem/tap/domain/TapWorkarounds.kt | 17 ---- .../tangem/tap/domain/config/Conditions.kt | 27 ------- .../tangem/tap/domain/config/ConfigLoader.kt | 39 ++++++---- .../tangem/tap/domain/config/ConfigManager.kt | 77 ++++++++----------- .../tangem/tap/domain/config/JsonModels.kt | 20 ++--- .../com/tangem/tap/domain/config/Models.kt | 53 ------------- .../features/wallet/redux/WalletMiddleware.kt | 9 +-- .../coinmarketcap/CoinMarketCapService.kt | 3 +- 13 files changed, 110 insertions(+), 237 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/TapConfig.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/config/Conditions.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/config/Models.kt diff --git a/app/src/main/assets/dev_config_values.json b/app/src/main/assets/dev_config_values.json index 532adfd5c1..dec5d88c02 100644 --- a/app/src/main/assets/dev_config_values.json +++ b/app/src/main/assets/dev_config_values.json @@ -1,16 +1,14 @@ -{ - "configValues": [ - { - "name": "coinMarketCapKey", - "value": "f6622117-c043-47a0-8975-9d673ce484de" - }, - { - "name": "moonPayApiKey", - "value": "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE" - }, - { - "name": "moonPayApiSecretKey", - "value": "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C" - } - ] -} \ No newline at end of file +[ + { + "name": "coinMarketCapKey", + "value": "f6622117-c043-47a0-8975-9d673ce484de" + }, + { + "name": "moonPayApiKey", + "value": "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE" + }, + { + "name": "moonPayApiSecretKey", + "value": "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C" + } +] \ No newline at end of file diff --git a/app/src/main/assets/dev_features.json b/app/src/main/assets/dev_features.json index ded87444cb..ede98d72ef 100644 --- a/app/src/main/assets/dev_features.json +++ b/app/src/main/assets/dev_features.json @@ -1,20 +1,18 @@ -{ - "features": [ - { - "name": "payIdIsEnabled", - "value": true - }, - { - "name": "usePayId", - "value": true - }, - { - "name": "showWelcomeMessageAtStart", - "value": false - }, - { - "name": "useTopUp", - "value": false - } - ] -} \ No newline at end of file +[ + { + "name": "payIdIsEnabled", + "value": true + }, + { + "name": "usePayId", + "value": true + }, + { + "name": "showWelcomeMessageAtStart", + "value": false + }, + { + "name": "useTopUp", + "value": false + } +] \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 24b84bb0d6..cea8c04e12 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -8,7 +8,10 @@ import com.tangem.tap.common.images.PicassoHelper import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.appReducer import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.config.* +import com.tangem.tap.domain.config.ConfigManager +import com.tangem.tap.domain.config.ConfigNameResolver +import com.tangem.tap.domain.config.LocalLoader +import com.tangem.tap.domain.config.RemoteLoader import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.network.createMoshi import com.tangem.tap.persistence.PreferencesStorage @@ -47,11 +50,11 @@ class TapApplication : Application() { private fun loadConfigs() { - val moshiAdapter = createMoshi().adapter(ConfigModel::class.java) + val moshi = createMoshi() val nameResolver = ConfigNameResolver.get() - val localLoader = LocalLoader(this, nameResolver, moshiAdapter) - val remoteLoader = RemoteLoader(nameResolver, moshiAdapter) + val localLoader = LocalLoader(this, nameResolver, moshi) + val remoteLoader = RemoteLoader(nameResolver, moshi) val configManager = ConfigManager(localLoader, remoteLoader) configManager.load { store.dispatch(GlobalAction.SetConfigManager(configManager)) } } diff --git a/app/src/main/java/com/tangem/tap/TapConfig.kt b/app/src/main/java/com/tangem/tap/TapConfig.kt deleted file mode 100644 index 9470f2935d..0000000000 --- a/app/src/main/java/com/tangem/tap/TapConfig.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.tangem.tap - -object TapConfig { - const val usePayId: Boolean = true - const val useTopUp: Boolean = true - const val coinMarketCapKey = "f6622117-c043-47a0-8975-9d673ce484de" - const val moonPayApiKey = "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE" - const val moonPayApiSecretKey = "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C" -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 47ea2833f3..7f9eb116b1 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -5,7 +5,6 @@ import com.tangem.blockchain.common.WalletManager import com.tangem.commands.CardStatus import com.tangem.commands.common.network.Result import com.tangem.common.extensions.toHexString -import com.tangem.tap.TapConfig import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.redux.global.CryptoCurrencyName @@ -26,7 +25,6 @@ import java.math.BigDecimal class TapWalletManager { private val payIdManager = PayIdManager() private val coinMarketCapService = CoinMarketCapService() - private var tapWorkarounds: TapWorkarounds? = null suspend fun loadWalletData() { val walletManager = store.state.globalState.scanNoteResponse?.walletManager @@ -84,7 +82,7 @@ class TapWalletManager { if (addAnalyticsEvent) { FirebaseAnalyticsHandler.triggerEvent(AnalyticsEvent.CARD_IS_SCANNED, data.card) } - tapWorkarounds = TapWorkarounds(data.card) + store.state.globalState.configManager?.onCardScanned(data.card) withContext(Dispatchers.Main) { store.dispatch(WalletAction.ResetState) store.dispatch(GlobalAction.SaveScanNoteResponse(data)) @@ -101,9 +99,11 @@ class TapWalletManager { store.dispatch(WalletAction.LoadData.Failure(TapError.NoInternetConnection)) return@withContext } + val config = store.state.globalState.configManager?.config?: return@withContext + store.dispatch(WalletAction.LoadWallet( data.walletManager.wallet, data.verifyResponse?.artworkInfo?.id, - tapWorkarounds?.isStart2Coin != true && TapConfig.useTopUp + !config.isStart2Coin && config.useTopUp )) store.dispatch(WalletAction.LoadArtwork(data.card, artworkId)) store.dispatch(WalletAction.LoadFiatRate) @@ -150,8 +150,9 @@ class TapWalletManager { private suspend fun loadPayIdIfNeeded(): Result? { + val config = store.state.globalState.configManager?.config val scanNoteResponse = store.state.globalState.scanNoteResponse - if (!TapConfig.usePayId || + if (config?.usePayId == false || scanNoteResponse?.walletManager?.wallet?.blockchain?.isPayIdSupported() == false) { return null } @@ -169,7 +170,8 @@ class TapWalletManager { is Result.Success -> { val payId = result.data if (payId == null) { - if (tapWorkarounds?.isPayIdCreationEnabled() == false) { + val config = store.state.globalState.configManager?.config?: return@withContext + if (!config.payIdIsEnabled) { store.dispatch(WalletAction.DisablePayId) } else { store.dispatch(WalletAction.LoadPayId.NotCreated) diff --git a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt deleted file mode 100644 index 9dc11ee062..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.tangem.tap.domain - -import com.tangem.commands.Card - -class TapWorkarounds(val card: Card) { - - val isStart2Coin: Boolean = card.cardData?.issuerName == START_2_COIN_ISSUER - - fun isPayIdCreationEnabled(): Boolean { - if (isStart2Coin) return false - return true - } - - companion object { - const val START_2_COIN_ISSUER = "start2coin" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/config/Conditions.kt b/app/src/main/java/com/tangem/tap/domain/config/Conditions.kt deleted file mode 100644 index b684bdfbb3..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/config/Conditions.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.tangem.tap.domain.config - -import com.tangem.commands.Card -import java.util.* - -/** -[REDACTED_AUTHOR] - */ -interface Condition { - fun isMet(): Boolean -} - -class CardIsStart2CoinCondition(private val card: Card?) : Condition { - - override fun isMet(): Boolean = card?.cardData?.issuerName?.toLowerCase(Locale.US) == "start2coin" -} - -class ConditionsFactory { - companion object { - fun create(name: String): Condition? { - return when (name) { - Feature.payIdIsEnabled -> CardIsStart2CoinCondition(null) - else -> null - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/config/ConfigLoader.kt b/app/src/main/java/com/tangem/tap/domain/config/ConfigLoader.kt index 3cc7d2aec7..d8ba2a3a96 100644 --- a/app/src/main/java/com/tangem/tap/domain/config/ConfigLoader.kt +++ b/app/src/main/java/com/tangem/tap/domain/config/ConfigLoader.kt @@ -4,6 +4,8 @@ import android.content.Context import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.ktx.remoteConfig import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types import com.tangem.wallet.BuildConfig import timber.log.Timber @@ -11,7 +13,7 @@ import timber.log.Timber [REDACTED_AUTHOR] */ interface ConfigLoader { - fun loadConfig(onComplete: (Config) -> Unit) + fun loadConfig(onComplete: (ConfigModel) -> Unit) } @@ -41,25 +43,29 @@ class ConfigNameResolver { } } +class KeyValueModel(val name: String, value: T?) + class LocalLoader( private val context: Context, private val nameResolver: NameResolver, - private val adapter: JsonAdapter + private val moshi: Moshi ) : ConfigLoader { - override fun loadConfig(onComplete: (Config) -> Unit) { + override fun loadConfig(onComplete: (ConfigModel) -> Unit) { val config = try { - val jsonFeatures = readAssetAsString(nameResolver.getFeaturesName()) - var configModel = adapter.fromJson(jsonFeatures) - val features = configModel?.toFeatures(ConfigType.Local) ?: mutableMapOf() + val featureType = Types.newParameterizedType(List::class.java, FeatureModel::class.java) + val featureAdapter: JsonAdapter> = moshi.adapter(featureType) + val valuesType = Types.newParameterizedType(List::class.java, ConfigValueModel::class.java) + val valuesAdapter: JsonAdapter> = moshi.adapter(valuesType) + val jsonFeatures = readAssetAsString(nameResolver.getFeaturesName()) val jsonConfigValues = readAssetAsString(nameResolver.getConfigValuesName()) - configModel = adapter.fromJson(jsonConfigValues) - val configValues = configModel?.toConfigValues() ?: mutableMapOf() - Config(features, configValues) + + ConfigModel(featureAdapter.fromJson(jsonFeatures) ?: listOf(), + valuesAdapter.fromJson(jsonConfigValues) ?: listOf()) } catch (ex: Exception) { Timber.e(ex) - Config.empty() + ConfigModel.empty() } onComplete(config) } @@ -71,11 +77,11 @@ class LocalLoader( class RemoteLoader( private val nameResolver: NameResolver, - private val adapter: JsonAdapter + private val moshi: Moshi ) : ConfigLoader { - override fun loadConfig(onComplete: (Config) -> Unit) { - val emptyConfig = Config.empty() + override fun loadConfig(onComplete: (ConfigModel) -> Unit) { + val emptyConfig = ConfigModel.empty() val remoteConfig = Firebase.remoteConfig remoteConfig.fetchAndActivate().addOnCompleteListener { if (it.isSuccessful) { @@ -85,10 +91,9 @@ class RemoteLoader( onComplete(emptyConfig) return@addOnCompleteListener } - val configModel = adapter.fromJson(jsonConfig) - val features = configModel?.toFeatures(ConfigType.Remote) ?: mutableMapOf() - val configValues = configModel?.toConfigValues() ?: mutableMapOf() - onComplete(Config(features, configValues)) + val featureType = Types.newParameterizedType(List::class.java, FeatureModel::class.java) + val featureAdapter: JsonAdapter> = moshi.adapter(featureType) + onComplete(ConfigModel(featureAdapter.fromJson(jsonConfig) ?: listOf(), listOf())) } else { onComplete(emptyConfig) } diff --git a/app/src/main/java/com/tangem/tap/domain/config/ConfigManager.kt b/app/src/main/java/com/tangem/tap/domain/config/ConfigManager.kt index f064353cc6..a7faf046bf 100644 --- a/app/src/main/java/com/tangem/tap/domain/config/ConfigManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/config/ConfigManager.kt @@ -1,69 +1,56 @@ package com.tangem.tap.domain.config +import com.tangem.commands.Card import com.tangem.tangem_sdk_new.ui.animation.VoidCallback +import java.util.* /** [REDACTED_AUTHOR] */ -enum class ConfigType { - Local, Remote -} - -class Config( - val features: MutableMap, - val configValues: MutableMap -) { - companion object { - fun empty(): Config = Config(mutableMapOf(), mutableMapOf()) - } -} +data class ConfigState( + val coinMarketCapKey: String = "f6622117-c043-47a0-8975-9d673ce484de", + val moonPayApiKey: String = "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE", + val moonPayApiSecretKey: String = "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C", + val payIdIsEnabled: Boolean = true, + val usePayId: Boolean = true, + val useTopUp: Boolean = true, + val isStart2Coin: Boolean = false +) class ConfigManager( private val localLoader: ConfigLoader, private val remoteLoader: ConfigLoader ) { - private var localConfig: Config = Config.empty() - private var remoteConfig: Config = Config.empty() + private val usePayId = "usePayId" + private val payIdIsEnabled = "payIdIsEnabled" + private val useTopUp = "useTopUp" + private val isStart2Coin = "isStart2Coin" + + var config: ConfigState = ConfigState() + private set fun load(onComplete: VoidCallback? = null) { - localLoader.loadConfig { localConfig = it } + localLoader.loadConfig { + it.features?.forEach { feature -> updateFeature(feature.name, feature.value) } + } remoteLoader.loadConfig { - remoteConfig = it + it.features?.forEach { feature -> updateFeature(feature.name, feature.value) } onComplete?.invoke() } } - fun featureIsActive(name: String): Boolean { - return getFeatureWithHighestPriority(name)?.isActive() ?: false + fun onCardScanned(card: Card) { + updateFeature(isStart2Coin, card.cardData?.issuerName?.toLowerCase(Locale.US) == "start2coin") } - fun getFeature(name: String, type: ConfigType? = null): Feature? { - return when (type) { - ConfigType.Local -> localConfig.features[name] - ConfigType.Remote -> remoteConfig.features[name] - else -> getFeatureWithHighestPriority(name) + private fun updateFeature(name: String, value: Boolean?) { + val newValue = value ?: return + + when (name) { + usePayId -> config = config.copy(usePayId = newValue) + payIdIsEnabled -> config = config.copy(payIdIsEnabled = newValue) + useTopUp -> config = config.copy(useTopUp = newValue) + isStart2Coin -> config = config.copy(isStart2Coin = newValue) } } - - private fun getFeatureWithHighestPriority(name: String): Feature? { - // if a localFeature doesn't exist then a remoteFeature won't exist to - val localFeature = localConfig.features[name] ?: return null - - // if the localFeature has a condition, then it has higher priority than a remoteFeature - return if (localFeature.hasCondition()) { - localFeature - } else { - // if not then the remoteFeature has higher priority than the localFeature - // if the remoteFeature doesn't exist - used the localFeature - remoteConfig.features[name] ?: localFeature - } - } - - fun getConfigValue(name: String): ConfigurationValue? { - return remoteConfig.configValues[name] ?: localConfig.configValues[name] - } - - fun updateCondition(name: String, condition: Condition?) { - localConfig.features[name]?.updateCondition(condition) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt b/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt index 7b70001f1a..be99fff956 100644 --- a/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt +++ b/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt @@ -19,18 +19,8 @@ class ConfigValueModel( override val value: String ) : BaseConfigModel -class ConfigModel(val features: List?, val configValues: List?) - -fun ConfigModel.toFeatures(type: ConfigType): MutableMap { - return features?.map { AppFeature(type, it, ConditionsFactory.create(it.name)) } - ?.associateBy { it.name } - ?.toMutableMap() - ?: mutableMapOf() -} - -fun ConfigModel.toConfigValues(): MutableMap { - return configValues?.map { ConfigurationValue(it.name, it.value) } - ?.associateBy { it.name } - ?.toMutableMap() ?: mutableMapOf() -} - +class ConfigModel(val features: List?, val configValues: List?) { + companion object { + fun empty(): ConfigModel = ConfigModel(listOf(), listOf()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/config/Models.kt b/app/src/main/java/com/tangem/tap/domain/config/Models.kt deleted file mode 100644 index 8f40b8d367..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/config/Models.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.tangem.tap.domain.config - -/** -[REDACTED_AUTHOR] - */ - -interface Feature { - val name: String - val type: ConfigType - fun isActive(): Boolean - fun reset() - fun updateCondition(condition: Condition?) - fun hasCondition(): Boolean - - companion object { - const val usePayId = "usePayId" - const val payIdIsEnabled = "payIdIsEnabled" - const val useTopUp = "useTopUp" - } -} - -class AppFeature( - override val type: ConfigType, - private val featureModel: FeatureModel, - private var condition: Condition? -) : Feature { - override val name: String = featureModel.name - - override fun isActive(): Boolean { - return if (condition == null) featureModel.value ?: false - else condition!!.isMet() - } - - override fun reset() { - condition = null - } - - override fun updateCondition(condition: Condition?) { - if (type == ConfigType.Local) this.condition = condition - } - - override fun hasCondition(): Boolean { - return condition != null - } -} - -data class ConfigurationValue(val name: String, val value: String) { - companion object { - const val coinMarketCapKey = "coinMarketCapKey" - const val moonPayApiKey = "moonPayApiKey" - const val moonPayApiSecretKey = "moonPayApiSecretKey" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt index 1f0b4769ee..3b8e7a3fb5 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt @@ -19,7 +19,6 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.PayIdManager import com.tangem.tap.domain.TapError import com.tangem.tap.domain.TopUpHelper -import com.tangem.tap.domain.config.ConfigurationValue import com.tangem.tap.domain.extensions.toSendableAmounts import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.wallet.models.toPendingTransactions @@ -254,14 +253,12 @@ private class TopUpMiddleware { fun handle(action: WalletAction.TopUpAction) { when (action) { is WalletAction.TopUpAction.TopUp -> { - val configManager = store.state.globalState.configManager ?: return - val apiKey = configManager.getConfigValue(ConfigurationValue.moonPayApiKey)?.value ?: "" - val secretKey = configManager.getConfigValue(ConfigurationValue.moonPayApiSecretKey)?.value ?: "" + val config = store.state.globalState.configManager?.config ?: return val url = TopUpHelper.getUrl( store.state.walletState.currencyData.currencySymbol!!, store.state.walletState.addressData!!.address, - apiKey, - secretKey + config.moonPayApiKey, + config.moonPayApiSecretKey ) Timber.d(url) store.dispatch(WalletAction.TopUpAction.Start(url, TopUpHelper.REDIRECT_URL)) diff --git a/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapService.kt b/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapService.kt index b31b784929..fffc439820 100644 --- a/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapService.kt +++ b/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapService.kt @@ -3,7 +3,6 @@ package com.tangem.tap.network.coinmarketcap import com.tangem.commands.common.network.Result import com.tangem.commands.common.network.performRequest import com.tangem.tap.common.redux.global.FiatCurrencyName -import com.tangem.tap.domain.config.ConfigurationValue import com.tangem.tap.store import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -13,7 +12,7 @@ class CoinMarketCapService() { private val api: CoinMarketCapApi by lazy { CoinMarketCapApi.create(getApiKey()) } private fun getApiKey(): String { - return store.state.globalState.configManager?.getConfigValue(ConfigurationValue.coinMarketCapKey)?.value!! + return store.state.globalState.configManager?.config?.coinMarketCapKey ?: "" } suspend fun getRate(