Updated on 2026-08-14
This commit is contained in:
commit
7200be9827
22 changed files with 304 additions and 41 deletions
|
|
@ -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'
|
||||
|
|
|
|||
10
app/src/main/assets/features_dev.json
Normal file
10
app/src/main/assets/features_dev.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"name": "isWalletPayIdEnabled",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "isTopUpEnabled",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
10
app/src/main/assets/features_prod.json
Normal file
10
app/src/main/assets/features_prod.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"name": "isWalletPayIdEnabled",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "isTopUpEnabled",
|
||||
"value": false
|
||||
}
|
||||
]
|
||||
|
|
@ -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)) }
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -33,6 +33,9 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
|
|||
globalState
|
||||
}
|
||||
}
|
||||
is GlobalAction.SetConfigManager -> {
|
||||
globalState.copy(configManager = action.configManager)
|
||||
}
|
||||
else -> globalState
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String?>? {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<FeatureModel>> = moshi.adapter(featureType)
|
||||
val valuesType = Types.newParameterizedType(List::class.java, ConfigValueModel::class.java)
|
||||
val valuesAdapter: JsonAdapter<List<ConfigValueModel>> = 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<List<FeatureModel>> = moshi.adapter(featureType)
|
||||
onComplete(ConfigModel(featureAdapter.fromJson(jsonConfig) ?: listOf(), listOf()))
|
||||
} else {
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
FirebaseCrashlytics.getInstance().recordException(it)
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
26
app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt
Normal file
26
app/src/main/java/com/tangem/tap/domain/config/JsonModels.kt
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.tap.domain.config
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
||||
interface BaseConfigModel<V> {
|
||||
val name: String
|
||||
val value: V?
|
||||
}
|
||||
|
||||
class FeatureModel(
|
||||
override val name: String,
|
||||
override val value: Boolean
|
||||
) : BaseConfigModel<Boolean>
|
||||
|
||||
class ConfigValueModel(
|
||||
override val name: String,
|
||||
override val value: String
|
||||
) : BaseConfigModel<String>
|
||||
|
||||
class ConfigModel(val features: List<FeatureModel>?, val configValues: List<ConfigValueModel>?) {
|
||||
companion object {
|
||||
fun empty(): ConfigModel = ConfigModel(listOf(), listOf())
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue