diff --git a/app/build.gradle b/app/build.gradle index de5564ec62..6dac91f10b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,6 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' apply plugin: 'com.google.firebase.crashlytics' -//apply plugin: 'com.google.firebase.firebase-perf' apply plugin: 'com.google.gms.google-services' android { @@ -25,6 +24,7 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.debug + buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"prod\"' } debug { debuggable true @@ -34,6 +34,7 @@ android { firebaseCrashlytics { mappingFileUploadEnabled false } + buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"dev\"' } debug_beta { initWith debug @@ -98,6 +99,7 @@ dependencies { // Firebase implementation platform('com.google.firebase:firebase-bom:26.0.0') implementation 'com.google.firebase:firebase-crashlytics' + implementation 'com.google.firebase:firebase-config-ktx' implementation 'com.google.firebase:firebase-analytics-ktx' testImplementation 'junit:junit:4.13' diff --git a/app/src/main/assets/features_dev.json b/app/src/main/assets/features_dev.json new file mode 100644 index 0000000000..33cf6e331b --- /dev/null +++ b/app/src/main/assets/features_dev.json @@ -0,0 +1,10 @@ +[ + { + "name": "isWalletPayIdEnabled", + "value": true + }, + { + "name": "isTopUpEnabled", + "value": true + } +] \ No newline at end of file diff --git a/app/src/main/assets/features_prod.json b/app/src/main/assets/features_prod.json new file mode 100644 index 0000000000..ede61eb088 --- /dev/null +++ b/app/src/main/assets/features_prod.json @@ -0,0 +1,10 @@ +[ + { + "name": "isWalletPayIdEnabled", + "value": false + }, + { + "name": "isTopUpEnabled", + "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 b19bfc730e..5e43828af0 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -1,10 +1,18 @@ package com.tangem.tap import android.app.Application +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings 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.ConfigManager +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 import com.tangem.wallet.BuildConfig import org.rekotlin.Store @@ -20,11 +28,31 @@ lateinit var preferencesStorage: PreferencesStorage class TapApplication : Application() { override fun onCreate() { super.onCreate() + if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) + Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings { + this.minimumFetchIntervalInSeconds = 60 + }) + } else { + Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings { + this.minimumFetchIntervalInSeconds = 3600 + }) } + NetworkConnectivity.createInstance(store, this) preferencesStorage = PreferencesStorage(this) PicassoHelper.initPicassoWithCaching(this) + + loadConfigs() + } + + + private fun loadConfigs() { + val moshi = createMoshi() + val localLoader = LocalLoader(this, moshi) + val remoteLoader = RemoteLoader(moshi) + val configManager = ConfigManager(localLoader, remoteLoader) + configManager.load { store.dispatch(GlobalAction.SetConfigManager(configManager)) } } } \ No newline at end of file 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 219dbfb94a..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_live_YTDl4Uei4411FXLAFe2rn8R2qWSiQcm" - const val moonPayApiSecretKey = "sk_live_7wMjoyGTGAB3i1suQHszCWRRqJBRPsQF" -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index c0e641bffe..9fb73bdfcb 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -1,5 +1,6 @@ package com.tangem.tap.common.redux.global +import com.tangem.tap.domain.config.ConfigManager import com.tangem.tap.domain.tasks.ScanNoteResponse import org.rekotlin.Action import java.math.BigDecimal @@ -15,4 +16,5 @@ sealed class GlobalAction : Action { data class Success(val appCurrency: FiatCurrencyName) : GlobalAction() } data class UpdateWalletSignedHashes(val walletSignedHashes: Int?) : GlobalAction() + data class SetConfigManager(val configManager: ConfigManager) : GlobalAction() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 66fbb80140..2b27751177 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -33,6 +33,9 @@ fun globalReducer(action: Action, state: AppState): GlobalState { globalState } } + is GlobalAction.SetConfigManager -> { + globalState.copy(configManager = action.configManager) + } else -> globalState } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 9da6906d9c..f9e05cdeac 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -4,6 +4,7 @@ import com.tangem.commands.common.network.TangemService import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY import com.tangem.tap.domain.PayIdManager import com.tangem.tap.domain.TapWalletManager +import com.tangem.tap.domain.config.ConfigManager import com.tangem.tap.domain.tasks.ScanNoteResponse import com.tangem.tap.network.coinmarketcap.CoinMarketCapService import org.rekotlin.StateType @@ -16,6 +17,7 @@ data class GlobalState( val coinMarketCapService: CoinMarketCapService = CoinMarketCapService(), val tangemService: TangemService = TangemService(), val conversionRates: ConversionRates = ConversionRates(emptyMap()), + val configManager: ConfigManager? = null, val appCurrency: FiatCurrencyName = DEFAULT_FIAT_CURRENCY ) : StateType 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 7c38359430..27d0665a61 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -5,15 +5,16 @@ 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 import com.tangem.tap.common.redux.global.FiatCurrencyName import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.domain.config.ConfigManager import com.tangem.tap.domain.extensions.amountToCreateAccount import com.tangem.tap.domain.extensions.isNoAccountError import com.tangem.tap.domain.tasks.ScanNoteResponse +import com.tangem.tap.features.send.redux.AddressPayIdActionUi import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.network.coinmarketcap.CoinMarketCapService @@ -84,9 +85,18 @@ class TapWalletManager { FirebaseAnalyticsHandler.triggerEvent(AnalyticsEvent.CARD_IS_SCANNED, data.card) } TapWorkarounds.updateCard(data.card) + val configManager = store.state.globalState.configManager + if (TapWorkarounds.isStart2Coin) { + configManager?.turnOff(ConfigManager.isWalletPayIdEnabled) + configManager?.turnOff(ConfigManager.isTopUpEnabled) + } else { + configManager?.resetToDefault(ConfigManager.isWalletPayIdEnabled) + configManager?.resetToDefault(ConfigManager.isTopUpEnabled) + } withContext(Dispatchers.Main) { store.dispatch(WalletAction.ResetState) store.dispatch(GlobalAction.SaveScanNoteResponse(data)) + store.dispatch(AddressPayIdActionUi.ChangePayIdState(configManager?.config?.isWalletPayIdEnabled ?: false)) loadData(data) } } @@ -100,10 +110,10 @@ 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 - )) + data.walletManager.wallet, data.verifyResponse?.artworkInfo?.id, config.isTopUpEnabled)) store.dispatch(WalletAction.LoadArtwork(data.card, artworkId)) store.dispatch(WalletAction.LoadFiatRate) store.dispatch(WalletAction.LoadPayId) @@ -150,8 +160,8 @@ class TapWalletManager { private suspend fun loadPayIdIfNeeded(): Result? { val scanNoteResponse = store.state.globalState.scanNoteResponse - if (!TapConfig.usePayId || - scanNoteResponse?.walletManager?.wallet?.blockchain?.isPayIdSupported() == false) { + if (store.state.globalState.configManager?.config?.isWalletPayIdEnabled == false + || scanNoteResponse?.walletManager?.wallet?.blockchain?.isPayIdSupported() == false) { return null } val cardId = scanNoteResponse?.card?.cardId @@ -166,11 +176,12 @@ class TapWalletManager { withContext(Dispatchers.Main) { when (result) { is Result.Success -> { - val payId = result.data - if (TapWorkarounds.isPayIdEnabled() == false) { + val config = store.state.globalState.configManager?.config + if (config?.isWalletPayIdEnabled == false) { store.dispatch(WalletAction.DisablePayId) return@withContext } + val payId = result.data if (payId == null) { store.dispatch(WalletAction.LoadPayId.NotCreated) } else { diff --git a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt index de1640fd9c..bb5e44f015 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt @@ -12,10 +12,5 @@ object TapWorkarounds { isStart2Coin = card.cardData?.issuerName?.toLowerCase(Locale.US) == START_2_COIN_ISSUER } - fun isPayIdEnabled(): Boolean { - if (isStart2Coin) return false - return true - } - const val START_2_COIN_ISSUER = "start2coin" } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TopUpHelper.kt b/app/src/main/java/com/tangem/tap/domain/TopUpHelper.kt index 7494073c72..5f5ae80096 100644 --- a/app/src/main/java/com/tangem/tap/domain/TopUpHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/TopUpHelper.kt @@ -1,7 +1,6 @@ package com.tangem.tap.domain import android.net.Uri -import com.tangem.tap.TapConfig import com.tangem.tap.common.redux.global.CryptoCurrencyName import org.spongycastle.util.encoders.Base64 import javax.crypto.Mac @@ -19,12 +18,12 @@ class TopUpHelper { // private const val REDIRECT_URL_PATH = "&redirectUrl=" private const val SIGNATURE_PATH = "&signature=" - fun getUrl(cryptoCurrencyName: CryptoCurrencyName, walletAddress: String): String { - val originalQuery = API_KEY_PATH + TapConfig.moonPayApiKey.urlEncode() + + fun getUrl(cryptoCurrencyName: CryptoCurrencyName, walletAddress: String, apiKey: String, secretKey: String): String { + val originalQuery = API_KEY_PATH + apiKey.urlEncode() + CURRENCY_PATH + cryptoCurrencyName.urlEncode() + WALLET_ADDRESS_PATH + walletAddress.urlEncode() // REDIRECT_URL_PATH + REDIRECT_URL.urlEncode() - val signature = createSignature(originalQuery, TapConfig.moonPayApiSecretKey) + val signature = createSignature(originalQuery, secretKey) return BASE_URL + originalQuery + SIGNATURE_PATH + signature.urlEncode() } 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 new file mode 100644 index 0000000000..60bb343e02 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/config/ConfigLoader.kt @@ -0,0 +1,81 @@ +package com.tangem.tap.domain.config + +import android.content.Context +import com.google.firebase.crashlytics.FirebaseCrashlytics +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 + +/** +[REDACTED_AUTHOR] + */ +interface ConfigLoader { + fun loadConfig(onComplete: (ConfigModel) -> Unit) + + companion object { + const val featuresName = "features_${BuildConfig.CONFIG_ENVIRONMENT}" + const val configValuesName = "config_${BuildConfig.CONFIG_ENVIRONMENT}" + } +} + + +class LocalLoader( + private val context: Context, + private val moshi: Moshi +) : ConfigLoader { + + override fun loadConfig(onComplete: (ConfigModel) -> Unit) { + val config = try { + 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(ConfigLoader.featuresName) + val jsonConfigValues = readAssetAsString(ConfigLoader.configValuesName) + + ConfigModel(featureAdapter.fromJson(jsonFeatures) ?: listOf(), + valuesAdapter.fromJson(jsonConfigValues) ?: listOf()) + } catch (ex: Exception) { + Timber.e(ex) + ConfigModel.empty() + } + onComplete(config) + } + + private fun readAssetAsString(fileName: String): String { + return context.assets.open("$fileName.json").bufferedReader().readText() + } +} + +class RemoteLoader( + private val moshi: Moshi +) : ConfigLoader { + + override fun loadConfig(onComplete: (ConfigModel) -> Unit) { + val emptyConfig = ConfigModel.empty() + val remoteConfig = Firebase.remoteConfig + remoteConfig.fetchAndActivate().addOnCompleteListener { + if (it.isSuccessful) { + val config = remoteConfig.getValue(ConfigLoader.featuresName) + val jsonConfig = config.asString() + if (jsonConfig.isEmpty()) { + onComplete(emptyConfig) + return@addOnCompleteListener + } + 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) + } + }.addOnFailureListener { + FirebaseCrashlytics.getInstance().recordException(it) + onComplete(emptyConfig) + } + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..339aeb3124 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/config/ConfigManager.kt @@ -0,0 +1,90 @@ +package com.tangem.tap.domain.config + +import com.tangem.tangem_sdk_new.ui.animation.VoidCallback + +/** +[REDACTED_AUTHOR] + */ +data class Config( + val coinMarketCapKey: String = "f6622117-c043-47a0-8975-9d673ce484de", + val moonPayApiKey: String = "pk_test_kc90oYTANy7UQdBavDKGfL4K9l6VEPE", + val moonPayApiSecretKey: String = "sk_test_V8w4M19LbDjjYOt170s0tGuvXAgyEb1C", + val isWalletPayIdEnabled: Boolean = true, + val isTopUpEnabled: Boolean = false, +) + +class ConfigManager( + private val localLoader: ConfigLoader, + private val remoteLoader: ConfigLoader +) { + + var config: Config = Config() + private set + + private var defaultConfig = Config() + + fun load(onComplete: VoidCallback? = null) { + localLoader.loadConfig { config -> + config.features?.forEach { setupFeature(it.name, it.value) } + config.configValues?.forEach { setupKey(it.name, it.value) } + } + remoteLoader.loadConfig { config -> + config.features?.forEach { setupFeature(it.name, it.value) } + onComplete?.invoke() + } + } + + fun turnOff(name: String) { + when (name) { + isWalletPayIdEnabled -> config = config.copy(isWalletPayIdEnabled = false) + isTopUpEnabled -> config = config.copy(isTopUpEnabled = false) + } + } + + fun resetToDefault(name: String) { + when (name) { + isWalletPayIdEnabled -> config = config.copy(isWalletPayIdEnabled = defaultConfig.isWalletPayIdEnabled) + isTopUpEnabled -> config = config.copy(isTopUpEnabled = defaultConfig.isTopUpEnabled) + } + } + + private fun setupFeature(name: String, value: Boolean) { + val newValue = value ?: return + + when (name) { + isWalletPayIdEnabled -> { + config = config.copy(isWalletPayIdEnabled = newValue) + defaultConfig = defaultConfig.copy(isWalletPayIdEnabled = newValue) + } + isTopUpEnabled -> { + config = config.copy(isTopUpEnabled = newValue) + defaultConfig = defaultConfig.copy(isTopUpEnabled = newValue) + } + } + } + + private fun setupKey(name: String, value: String) { + when (name) { + coinMarketCapKey -> { + config = config.copy(coinMarketCapKey = value) + defaultConfig = defaultConfig.copy(coinMarketCapKey = value) + } + moonPayApiKey -> { + config = config.copy(moonPayApiKey = value) + defaultConfig = defaultConfig.copy(moonPayApiKey = value) + } + moonPayApiSecretKey -> { + config = config.copy(moonPayApiSecretKey = value) + defaultConfig = defaultConfig.copy(moonPayApiSecretKey = value) + } + } + } + + companion object { + const val isWalletPayIdEnabled = "isWalletPayIdEnabled" + const val isTopUpEnabled = "useTopUp" + 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/domain/config/JsonModels.kt b/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt new file mode 100644 index 0000000000..1b7272765b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt @@ -0,0 +1,26 @@ +package com.tangem.tap.domain.config + +/** +[REDACTED_AUTHOR] + */ + +interface BaseConfigModel { + val name: String + val value: V? +} + +class FeatureModel( + override val name: String, + override val value: Boolean +) : BaseConfigModel + +class ConfigValueModel( + override val name: String, + override val value: String +) : BaseConfigModel + +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/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index 911a51af79..e54f0f07dc 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -33,6 +33,7 @@ sealed class AddressPayIdActionUi : SendScreenActionUi { object CheckAddressPayId : AddressPayIdActionUi() data class SetTruncateHandler(val handler: (String) -> String) : AddressPayIdActionUi() data class TruncateOrRestore(val truncate: Boolean) : AddressPayIdActionUi() + data class ChangePayIdState(val walletPayIdEnabled: Boolean): AddressPayIdActionUi() } sealed class AddressPayIdVerifyAction : SendScreenAction { diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt index 680654633b..74fdac0d5d 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt @@ -4,7 +4,6 @@ import com.tangem.blockchain.common.Wallet import com.tangem.commands.common.network.Result import com.tangem.tap.common.redux.AppState import com.tangem.tap.domain.PayIdManager -import com.tangem.tap.domain.TapWorkarounds import com.tangem.tap.domain.isPayIdSupported import com.tangem.tap.features.send.redux.AddressPayIdActionUi import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction @@ -15,6 +14,7 @@ import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerifica import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdWalletAddress import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.scope +import com.tangem.tap.store import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -49,7 +49,7 @@ internal class AddressPayIdMiddleware { private fun setAddressAndCheck(data: String, isUserInput: Boolean, dispatch: (Action) -> Unit) { val potentialPayId = data.toLowerCase() - if (PayIdManager.isPayId(potentialPayId) && TapWorkarounds.isPayIdEnabled()) { + if (PayIdManager.isPayId(potentialPayId) && isPayIdEnabled()) { dispatch(SetPayIdWalletAddress(potentialPayId, "", isUserInput)) } else { dispatch(SetWalletAddress(data, isUserInput)) @@ -63,7 +63,7 @@ internal class AddressPayIdMiddleware { val addressPayId = sendState.addressPayIdState.normalFieldValue ?: return val isUserInput = sendState.addressPayIdState.viewFieldValue.isFromUserInput - if (PayIdManager.isPayId(addressPayId) && TapWorkarounds.isPayIdEnabled()) { + if (PayIdManager.isPayId(addressPayId) && isPayIdEnabled()) { verifyPayId(addressPayId, wallet, isUserInput, dispatch) } else { verifyAddress(addressPayId, wallet, isUserInput, dispatch) @@ -152,10 +152,14 @@ internal class AddressPayIdMiddleware { } } - if (PayIdManager.isPayId(addressPayId) && TapWorkarounds.isPayIdEnabled()) { + if (PayIdManager.isPayId(addressPayId) && isPayIdEnabled()) { verifyPayId(addressPayId, wallet, false, internalDispatcher) } else { verifyAddress(addressPayId, wallet, false, internalDispatcher) } } + + private fun isPayIdEnabled(): Boolean { + return store.state.globalState.configManager?.config?.isWalletPayIdEnabled ?: false + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt index e7c726241f..d7a1c97f10 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt @@ -30,6 +30,7 @@ class AddressPayIdReducer : SendInternalReducer { is AddressPayIdActionUi.PasteAddressPayId -> return sendState is AddressPayIdActionUi.CheckClipboard -> return sendState is AddressPayIdActionUi.CheckAddressPayId -> return sendState + is AddressPayIdActionUi.ChangePayIdState -> state.copy(walletPayIdEnabled = action.walletPayIdEnabled) } return updateLastState(sendState.copy(addressPayIdState = result), result) } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt index dfcc6ca4c5..b7a1622789 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt @@ -9,6 +9,7 @@ data class AddressPayIdState( val recipientWalletAddress: String? = null, val error: AddressPayIdVerifyAction.Error? = null, val truncateHandler: ((String) -> String)? = null, + val walletPayIdEnabled: Boolean = false, val pasteIsEnabled: Boolean = false ) : SendScreenState { diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index bdd2e9f3c4..c6065b1752 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -10,7 +10,6 @@ import com.tangem.tap.common.redux.getMessageString import com.tangem.tap.common.text.DecimalDigitsInputFilter import com.tangem.tap.common.toggleWidget.ProgressState import com.tangem.tap.domain.MultiMessageError -import com.tangem.tap.domain.TapWorkarounds import com.tangem.tap.domain.assembleErrors import com.tangem.tap.features.send.BaseStoreFragment import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error @@ -104,7 +103,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber val til = fg.tilAddressOrPayId val parsedError = parseError(til.context, state.error) - val hintResId = if (TapWorkarounds.isPayIdEnabled()) { + val hintResId = if (state.walletPayIdEnabled) { R.string.send_destination_hint_address_payid }else { R.string.send_destination_hint_address 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 d1ea1faa17..129123e56c 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 @@ -255,9 +255,12 @@ private class TopUpMiddleware { fun handle(action: WalletAction.TopUpAction) { when (action) { is WalletAction.TopUpAction.TopUp -> { + val config = store.state.globalState.configManager?.config ?: return val url = TopUpHelper.getUrl( store.state.walletState.currencyData.currencySymbol!!, - store.state.walletState.addressData!!.address + store.state.walletState.addressData!!.address, + config.moonPayApiKey, + config.moonPayApiSecretKey ) val customTabsIntent = CustomTabsIntent.Builder() .setToolbarColor(action.toolbarColor) diff --git a/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapApi.kt b/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapApi.kt index 47889ff06d..5d78846280 100644 --- a/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapApi.kt +++ b/app/src/main/java/com/tangem/tap/network/coinmarketcap/CoinMarketCapApi.kt @@ -1,6 +1,5 @@ package com.tangem.tap.network.coinmarketcap -import com.tangem.tap.TapConfig import com.tangem.tap.network.createRetrofitInstance import okhttp3.Interceptor import okhttp3.Response @@ -23,20 +22,20 @@ interface CoinMarketCapApi { companion object { private const val baseUrl = "https://pro-api.coinmarketcap.com/" - fun create(): CoinMarketCapApi { + fun create(apiKey: String): CoinMarketCapApi { return createRetrofitInstance( baseUrl, - listOf(createCoinMarketRequestInterceptor()), + listOf(createCoinMarketRequestInterceptor(apiKey)), ).create(CoinMarketCapApi::class.java) } } } -private fun createCoinMarketRequestInterceptor(): Interceptor { +private fun createCoinMarketRequestInterceptor(apiKey: String): Interceptor { return object : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val requestBuilder = chain.request().newBuilder() - requestBuilder.addHeader("X-CMC_PRO_API_KEY", TapConfig.coinMarketCapKey) + requestBuilder.addHeader("X-CMC_PRO_API_KEY", apiKey) return chain.proceed(requestBuilder.build()) } } 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 4dc7931623..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,12 +3,17 @@ 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.store import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.math.BigDecimal -class CoinMarketCapService { - private val api: CoinMarketCapApi by lazy { CoinMarketCapApi.create() } +class CoinMarketCapService() { + private val api: CoinMarketCapApi by lazy { CoinMarketCapApi.create(getApiKey()) } + + private fun getApiKey(): String { + return store.state.globalState.configManager?.config?.coinMarketCapKey ?: "" + } suspend fun getRate( currency: String, fiatCurrency: FiatCurrencyName? = null