Updated on 2026-08-14
This commit is contained in:
parent
b73b6c3fe7
commit
d5299f8094
15 changed files with 119 additions and 10 deletions
|
|
@ -54,6 +54,7 @@ import com.tangem.domain.wallets.repository.WalletsRepository
|
|||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.operations.attestation.api.TangemApiServiceLogging
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler
|
||||
|
|
@ -276,6 +277,10 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
createNetworkLoggingInterceptor(),
|
||||
ChuckerInterceptor(this),
|
||||
)
|
||||
TangemApiServiceLogging.addInterceptors(
|
||||
createNetworkLoggingInterceptor(),
|
||||
ChuckerInterceptor(this),
|
||||
)
|
||||
}
|
||||
|
||||
derivationsFinder = DerivationsFinder(
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
|||
import com.tangem.crypto.bip39.Wordlist
|
||||
import com.tangem.data.card.sdk.CardSdkOwner
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||
import com.tangem.sdk.DefaultSessionViewDelegate
|
||||
import com.tangem.sdk.api.featuretoggles.CardSdkFeatureToggles
|
||||
import com.tangem.sdk.extensions.*
|
||||
|
|
@ -23,6 +29,11 @@ import com.tangem.sdk.nfc.NfcManager
|
|||
import com.tangem.sdk.storage.create
|
||||
import com.tangem.tap.foregroundActivityObserver
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -37,6 +48,8 @@ internal class DefaultCardSdkProvider @Inject constructor(
|
|||
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val cardSdkFeatureToggles: CardSdkFeatureToggles,
|
||||
private val apiConfigsManager: ApiConfigsManager,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
) : CardSdkProvider, CardSdkOwner {
|
||||
|
||||
private val observer = Observer()
|
||||
|
|
@ -46,6 +59,17 @@ internal class DefaultCardSdkProvider @Inject constructor(
|
|||
override val sdk: TangemSdk
|
||||
get() = holder?.sdk ?: tryToRegisterWithForegroundActivity()
|
||||
|
||||
init {
|
||||
appPreferencesStore.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
.map { it[ApiConfig.ID.TangemCardSdk.name] == ApiEnvironment.PROD }
|
||||
.onEach { isProd ->
|
||||
holder?.let {
|
||||
it.sdk.config.isTangemAttestationProdEnv = isProd
|
||||
}
|
||||
}
|
||||
.launchIn(CoroutineScope(SupervisorJob() + dispatchers.main))
|
||||
}
|
||||
|
||||
override fun register(activity: FragmentActivity) = runBlocking(dispatchers.mainImmediate) {
|
||||
if (activity.isDestroyed || activity.isFinishing || activity.isChangingConfigurations) {
|
||||
val message = "Tangem SDK owner registration skipped: activity is destroyed or finishing"
|
||||
|
|
@ -133,6 +157,9 @@ internal class DefaultCardSdkProvider @Inject constructor(
|
|||
wordlist = Wordlist.getWordlist(activity),
|
||||
config = config.apply {
|
||||
isNewOnlineAttestationEnabled = cardSdkFeatureToggles.isNewAttestationEnabled
|
||||
|
||||
val apiConfig = apiConfigsManager.getEnvironmentConfig(id = ApiConfig.ID.TangemCardSdk)
|
||||
isTangemAttestationProdEnv = apiConfig.environment == ApiEnvironment.PROD
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -186,7 +213,6 @@ internal class DefaultCardSdkProvider @Inject constructor(
|
|||
|
||||
val config = Config(
|
||||
linkedTerminal = true,
|
||||
allowUntrustedCards = true,
|
||||
filter = CardFilter(
|
||||
allowedCardTypes = FirmwareVersion.FirmwareType.entries.toList(),
|
||||
maxFirmwareVersion = FirmwareVersion(major = 6, minor = 33),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ object Wallet2MockContent : MockContent {
|
|||
name = "TANGEM 2.0",
|
||||
publicKey = byteArrayOf(2, -120, 89, -52, -60, 36, -73, -17, 103, 107, -110, -36, 3, 110, -122, 72, 43, -38, 8, 30, -50, 25, -23, -17, 38, 94, 5, -112, -20, 9, 54, -24, -32),
|
||||
),
|
||||
manufacturer = Card.Manufacturer(
|
||||
name = "TANGEM SDK",
|
||||
manufactureDate = Date(1743759687),
|
||||
signature = byteArrayOf(),
|
||||
),
|
||||
walletCurves = listOf(
|
||||
EllipticCurve.Secp256k1,
|
||||
EllipticCurve.Ed25519,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ object WalletMockContent : MockContent {
|
|||
name = "TANGEM AG",
|
||||
publicKey = byteArrayOf(3, 86, -25, -61, 55, 99, 41, -33, -82, 115, -120, -33, 22, -107, 103, 3, -122, 16, 60, -110, 72, 106, -121, 100, 79, -87, -27, 18, -55, -49, 78, -110, -2),
|
||||
),
|
||||
manufacturer = Card.Manufacturer(
|
||||
name = "TANGEM",
|
||||
manufactureDate = Date(1743759687),
|
||||
signature = byteArrayOf(),
|
||||
),
|
||||
walletCurves = listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519, EllipticCurve.Bls12381G2Aug),
|
||||
firmwareVersion = FirmwareVersion(
|
||||
major = 4,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ sealed class ApiConfig {
|
|||
StakeKit,
|
||||
TangemVisaAuth,
|
||||
TangemVisa,
|
||||
TangemCardSdk,
|
||||
}
|
||||
|
||||
private fun initializeId(): ID {
|
||||
|
|
@ -35,6 +36,7 @@ sealed class ApiConfig {
|
|||
is StakeKit -> ID.StakeKit
|
||||
is TangemVisaAuth -> ID.TangemVisaAuth
|
||||
is TangemVisa -> ID.TangemVisa
|
||||
is TangemCardSdk -> ID.TangemCardSdk
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.datasource.api.common.config
|
||||
|
||||
/**
|
||||
* Tangem API [ApiConfig] that used in CardSDK
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class TangemCardSdk : ApiConfig() {
|
||||
|
||||
override val defaultEnvironment: ApiEnvironment = ApiEnvironment.PROD
|
||||
|
||||
override val environmentConfigs: List<ApiEnvironmentConfig> = listOf(
|
||||
createDevEnvironment(),
|
||||
createProdEnvironment(),
|
||||
)
|
||||
|
||||
private fun createDevEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.DEV,
|
||||
baseUrl = "[REDACTED_ENV_URL]",
|
||||
)
|
||||
|
||||
private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.tangem-tech.com/",
|
||||
)
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import com.tangem.datasource.api.common.config.ApiEnvironmentConfig
|
|||
interface ApiConfigsManager {
|
||||
|
||||
/** Initialize resources */
|
||||
suspend fun initialize() {}
|
||||
fun initialize() {}
|
||||
|
||||
/** Get environment config by [id] */
|
||||
fun getEnvironmentConfig(id: ApiConfig.ID): ApiEnvironmentConfig
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.datasource.local.preferences.PreferencesKeys
|
|||
import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +29,7 @@ internal class DevApiConfigsManager(
|
|||
|
||||
private val _apiConfigs = MutableStateFlow(value = apiConfigs.associateWith { it.defaultEnvironment })
|
||||
|
||||
override suspend fun initialize() {
|
||||
override fun initialize() {
|
||||
// We can't use appPreferencesStore.getObjectMap as base flow,
|
||||
// because we should keep possibility to work with configs synchronous.
|
||||
// See [getBaseUrl]
|
||||
|
|
@ -42,7 +43,7 @@ internal class DevApiConfigsManager(
|
|||
}
|
||||
}
|
||||
}
|
||||
.launchIn(CoroutineScope(dispatchers.main))
|
||||
.launchIn(CoroutineScope(SupervisorJob() + dispatchers.main))
|
||||
}
|
||||
|
||||
override fun getEnvironmentConfig(id: ApiConfig.ID): ApiEnvironmentConfig {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ package com.tangem.datasource.di
|
|||
|
||||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.datasource.api.common.config.*
|
||||
import com.tangem.datasource.api.common.config.Express
|
||||
import com.tangem.datasource.api.common.config.StakeKit
|
||||
import com.tangem.datasource.api.common.config.TangemTech
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
|
|
@ -48,4 +45,8 @@ internal object ApiConfigsModule {
|
|||
@Provides
|
||||
@IntoSet
|
||||
fun provideTangemVisaConfig(appVersionProvider: AppVersionProvider): ApiConfig = TangemVisa(appVersionProvider)
|
||||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideTangemCardSdkConfig(): ApiConfig = TangemCardSdk()
|
||||
}
|
||||
|
|
@ -89,6 +89,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
is StakeKit -> createStakeKitModel()
|
||||
is TangemVisaAuth -> createVisaAuthModel()
|
||||
is TangemVisa -> createVisaModel()
|
||||
is TangemCardSdk -> createTangemCardSdkModel()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +205,16 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createTangemCardSdkModel(): Model {
|
||||
return Model(
|
||||
id = ApiConfig.ID.TangemCardSdk,
|
||||
expected = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.tangem-tech.com/",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.checkHeaderValueOrEmpty(): String {
|
||||
for (i in this.indices) {
|
||||
val c = this[i]
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.tangem.common.UserCodeType
|
|||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.common.core.UserCodeRequestPolicy
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
|
||||
/**
|
||||
|
|
@ -70,4 +70,8 @@ internal class DefaultCardSdkConfigRepository(
|
|||
override fun setLinkedTerminal(isLinked: Boolean?) {
|
||||
sdk.config.linkedTerminal = isLinked
|
||||
}
|
||||
|
||||
override fun setTangemApiProdEnvFlag(flag: Boolean) {
|
||||
sdk.config.isTangemAttestationProdEnv = flag
|
||||
}
|
||||
}
|
||||
|
|
@ -36,4 +36,7 @@ interface CardSdkConfigRepository {
|
|||
|
||||
/** Set linked terminal by [isLinked] */
|
||||
fun setLinkedTerminal(isLinked: Boolean?)
|
||||
|
||||
/** Set [flag] that determines whether to use Prod environment for Tangem API */
|
||||
fun setTangemApiProdEnvFlag(flag: Boolean)
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ dependencies {
|
|||
/** Domain modules */
|
||||
implementation(projects.domain.appTheme)
|
||||
implementation(projects.domain.appTheme.models)
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.feedback)
|
||||
|
||||
/** Other libraries */
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.datasource.api.common.config.ApiConfig
|
|||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.datasource.api.common.config.managers.MutableApiConfigsManager
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.feature.tester.impl.BuildConfig
|
||||
import com.tangem.feature.tester.impl.R
|
||||
import com.tangem.feature.tester.presentation.environments.state.EnvironmentTogglesScreenUM
|
||||
|
|
@ -28,6 +29,7 @@ import javax.inject.Inject
|
|||
@HiltViewModel
|
||||
internal class EnvironmentsTogglesViewModel @Inject constructor(
|
||||
apiConfigsManager: ApiConfigsManager,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Current ui state */
|
||||
|
|
@ -92,7 +94,24 @@ internal class EnvironmentsTogglesViewModel @Inject constructor(
|
|||
|
||||
private fun onToggleValueChange(id: String, name: String) {
|
||||
viewModelScope.launch {
|
||||
mutableApiConfigsManager.changeEnvironment(id = id, environment = ApiEnvironment.valueOf(name))
|
||||
val environment = ApiEnvironment.valueOf(name)
|
||||
|
||||
handleIfTangemCardSdkConfig(id = id, environment = environment)
|
||||
|
||||
mutableApiConfigsManager.changeEnvironment(id = id, environment = environment)
|
||||
}
|
||||
}
|
||||
|
||||
/** Special logic for [ApiConfig.ID.TangemCardSdk] */
|
||||
private fun handleIfTangemCardSdkConfig(id: String, environment: ApiEnvironment) {
|
||||
if (id == ApiConfig.ID.TangemCardSdk.name) {
|
||||
cardSdkConfigRepository.setTangemApiProdEnvFlag(
|
||||
flag = when (environment) {
|
||||
ApiEnvironment.PROD -> true
|
||||
ApiEnvironment.DEV -> false
|
||||
else -> false
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
[versions]
|
||||
tangemBlockchainSdk = "develop-1000"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-445"
|
||||
tangemCardSdk = "develop-449"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
tangemVico = "2.0.0-alpha.25-tangem-developments8"
|
||||
#tangemVico = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue