Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-25 15:24:36 +04:00
parent 286e28223c
commit aeef2b3945
28 changed files with 158 additions and 240 deletions

View file

@ -19,7 +19,7 @@ import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.data.card.TransactionSignerFactory import com.tangem.data.card.TransactionSignerFactory
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
@ -57,12 +57,12 @@ import dagger.hilt.components.SingletonComponent
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
interface ApplicationEntryPoint { interface ApplicationEntryPoint {
fun getEnvironmentConfigStorage(): EnvironmentConfigStorage
fun getAppStateHolder(): AppStateHolder fun getAppStateHolder(): AppStateHolder
fun getIssuersConfigStorage(): IssuersConfigStorage fun getIssuersConfigStorage(): IssuersConfigStorage
fun getEnvironmentConfig(): EnvironmentConfig
fun getFeatureTogglesManager(): FeatureTogglesManager fun getFeatureTogglesManager(): FeatureTogglesManager
fun getExcludedBlockchainsManager(): ExcludedBlockchainsManager fun getExcludedBlockchainsManager(): ExcludedBlockchainsManager

View file

@ -36,7 +36,6 @@ import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.environment.EnvironmentConfig import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
@ -80,7 +79,6 @@ import dagger.hilt.EntryPoints
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.rekotlin.Store import org.rekotlin.Store
import timber.log.Timber import timber.log.Timber
@ -97,12 +95,12 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
private val appStateHolder: AppStateHolder private val appStateHolder: AppStateHolder
get() = entryPoint.getAppStateHolder() get() = entryPoint.getAppStateHolder()
private val environmentConfigStorage: EnvironmentConfigStorage
get() = entryPoint.getEnvironmentConfigStorage()
private val issuersConfigStorage: IssuersConfigStorage private val issuersConfigStorage: IssuersConfigStorage
get() = entryPoint.getIssuersConfigStorage() get() = entryPoint.getIssuersConfigStorage()
private val environmentConfig: EnvironmentConfig
get() = entryPoint.getEnvironmentConfig()
private val featureTogglesManager: FeatureTogglesManager private val featureTogglesManager: FeatureTogglesManager
get() = entryPoint.getFeatureTogglesManager() get() = entryPoint.getFeatureTogglesManager()
@ -306,9 +304,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
Timber.i(excludedBlockchainsManager.toString()) Timber.i(excludedBlockchainsManager.toString())
} }
runBlocking { initWithConfigDependency(environmentConfig = environmentConfig)
initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize())
}
abTestsManager.init() abTestsManager.init()
@ -345,7 +341,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
appStateHolder.mainStore = store appStateHolder.mainStore = store
wcInitializeUseCase.init( wcInitializeUseCase.init(
projectId = environmentConfigStorage.getConfigSync().walletConnectProjectId, projectId = environmentConfig.walletConnectProjectId,
) )
} }
@ -376,7 +372,6 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
shareManager = shareManager, shareManager = shareManager,
appRouter = appRouter, appRouter = appRouter,
transactionSignerFactory = transactionSignerFactory, transactionSignerFactory = transactionSignerFactory,
environmentConfigStorage = environmentConfigStorage,
onboardingV2FeatureToggles = onboardingV2FeatureToggles, onboardingV2FeatureToggles = onboardingV2FeatureToggles,
onboardingRepository = onboardingRepository, onboardingRepository = onboardingRepository,
excludedBlockchains = excludedBlockchains, excludedBlockchains = excludedBlockchains,

View file

@ -1,7 +1,7 @@
package com.tangem.tap.di package com.tangem.tap.di
import com.tangem.datasource.api.moonpay.MoonPayApi import com.tangem.datasource.api.moonpay.MoonPayApi
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.ScanCardUseCase
import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.exchange.RampStateManager
@ -69,14 +69,14 @@ internal object ActivityModule {
@Provides @Provides
@Singleton @Singleton
fun provideExchangeService( fun provideExchangeService(
environmentConfigStorage: EnvironmentConfigStorage,
getSelectedWalletUseCase: GetSelectedWalletUseCase, getSelectedWalletUseCase: GetSelectedWalletUseCase,
moonPayApi: MoonPayApi, moonPayApi: MoonPayApi,
environmentConfig: EnvironmentConfig,
): SellService { ): SellService {
return MoonPayService( return MoonPayService(
api = moonPayApi, api = moonPayApi,
apiKeyProvider = Provider { environmentConfigStorage.getConfigSync().moonPayApiKey }, apiKey = environmentConfig.moonPayApiKey,
secretKeyProvider = Provider { environmentConfigStorage.getConfigSync().moonPayApiSecretKey }, secretKey = environmentConfig.moonPayApiSecretKey,
userWalletProvider = { getSelectedWalletUseCase.sync().getOrNull() }, userWalletProvider = { getSelectedWalletUseCase.sync().getOrNull() },
) )
} }

View file

@ -3,7 +3,7 @@ package com.tangem.tap.network.auth
import com.tangem.common.extensions.toHexString import com.tangem.common.extensions.toHexString
import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.api.common.config.ApiEnvironment import com.tangem.datasource.api.common.config.ApiEnvironment
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.utils.Provider import com.tangem.utils.Provider
@ -11,7 +11,7 @@ import com.tangem.utils.ProviderSuspend
internal class DefaultAuthProvider( internal class DefaultAuthProvider(
private val userWalletsListRepository: UserWalletsListRepository, private val userWalletsListRepository: UserWalletsListRepository,
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
) : AuthProvider { ) : AuthProvider {
override suspend fun getCardPublicKey(): String { override suspend fun getCardPublicKey(): String {
@ -47,11 +47,11 @@ internal class DefaultAuthProvider(
ApiEnvironment.DEV, ApiEnvironment.DEV,
ApiEnvironment.DEV_2, ApiEnvironment.DEV_2,
ApiEnvironment.DEV_3, ApiEnvironment.DEV_3,
-> environmentConfigStorage.getConfigSync().tangemApiKeyDev -> environmentConfig.tangemApiKeyDev
ApiEnvironment.STAGE_2, ApiEnvironment.STAGE_2,
ApiEnvironment.STAGE, ApiEnvironment.STAGE,
-> environmentConfigStorage.getConfigSync().tangemApiKeyStage -> environmentConfig.tangemApiKeyStage
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().tangemApiKey ApiEnvironment.PROD -> environmentConfig.tangemApiKey
} ?: error("No tangem tech api config provided") } ?: error("No tangem tech api config provided")
} }
} }
@ -60,8 +60,8 @@ internal class DefaultAuthProvider(
return ProviderSuspend { return ProviderSuspend {
when (apiEnvironment.invoke()) { when (apiEnvironment.invoke()) {
ApiEnvironment.DEV, ApiEnvironment.DEV,
-> environmentConfigStorage.getConfigSync().gaslessTxApiKeyDev -> environmentConfig.gaslessTxApiKeyDev
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().gaslessTxApiKey ApiEnvironment.PROD -> environmentConfig.gaslessTxApiKey
else -> error("No gasless tx api config provided for ${apiEnvironment.invoke()}") else -> error("No gasless tx api config provided for ${apiEnvironment.invoke()}")
} ?: error("No gasless tx api config provided") } ?: error("No gasless tx api config provided")
} }

View file

@ -1,15 +1,15 @@
package com.tangem.tap.network.auth package com.tangem.tap.network.auth
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.domain.staking.model.ethpool.P2PEthPoolStakingConfig import com.tangem.domain.staking.model.ethpool.P2PEthPoolStakingConfig
import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.lib.auth.P2PEthPoolAuthProvider
internal class DefaultP2PEthPoolAuthProvider( internal class DefaultP2PEthPoolAuthProvider(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
) : P2PEthPoolAuthProvider { ) : P2PEthPoolAuthProvider {
override fun getApiKey(): String { override fun getApiKey(): String {
val keys = environmentConfigStorage.getConfigSync().p2pApiKey val keys = environmentConfig.p2pApiKey
?: error("No P2P api keys provided") ?: error("No P2P api keys provided")
return if (P2PEthPoolStakingConfig.USE_TESTNET) keys.hoodi else keys.mainnet return if (P2PEthPoolStakingConfig.USE_TESTNET) keys.hoodi else keys.mainnet

View file

@ -1,13 +1,13 @@
package com.tangem.tap.network.auth package com.tangem.tap.network.auth
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.lib.auth.StakeKitAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider
internal class DefaultStakeKitAuthProvider( internal class DefaultStakeKitAuthProvider(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
) : StakeKitAuthProvider { ) : StakeKitAuthProvider {
override fun getApiKey(): String { override fun getApiKey(): String {
return environmentConfigStorage.getConfigSync().stakeKitApiKey ?: error("No StakeKit api key provided") return environmentConfig.stakeKitApiKey ?: error("No StakeKit api key provided")
} }
} }

View file

@ -1,7 +1,7 @@
package com.tangem.tap.network.auth.di package com.tangem.tap.network.auth.di
import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.ExpressAuthProvider
import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.lib.auth.P2PEthPoolAuthProvider
@ -22,11 +22,11 @@ internal class AuthModule {
@Singleton @Singleton
fun provideAuthProvider( fun provideAuthProvider(
userWalletsListRepository: UserWalletsListRepository, userWalletsListRepository: UserWalletsListRepository,
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
): AuthProvider { ): AuthProvider {
return DefaultAuthProvider( return DefaultAuthProvider(
userWalletsListRepository = userWalletsListRepository, userWalletsListRepository = userWalletsListRepository,
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
) )
} }
@ -38,14 +38,14 @@ internal class AuthModule {
@Provides @Provides
@Singleton @Singleton
fun provideStakeKitAuthProvider(environmentConfigStorage: EnvironmentConfigStorage): StakeKitAuthProvider { fun provideStakeKitAuthProvider(environmentConfig: EnvironmentConfig): StakeKitAuthProvider {
return DefaultStakeKitAuthProvider(environmentConfigStorage) return DefaultStakeKitAuthProvider(environmentConfig)
} }
@Provides @Provides
@Singleton @Singleton
fun provideP2PEthPoolAuthProvider(environmentConfigStorage: EnvironmentConfigStorage): P2PEthPoolAuthProvider { fun provideP2PEthPoolAuthProvider(environmentConfig: EnvironmentConfig): P2PEthPoolAuthProvider {
return DefaultP2PEthPoolAuthProvider(environmentConfigStorage) return DefaultP2PEthPoolAuthProvider(environmentConfig)
} }
@Provides @Provides

View file

@ -19,7 +19,6 @@ import com.tangem.tap.domain.model.Currency
import com.tangem.tap.network.exchangeServices.SellService import com.tangem.tap.network.exchangeServices.SellService
import com.tangem.tap.network.exchangeServices.SellServiceInitializationStatus import com.tangem.tap.network.exchangeServices.SellServiceInitializationStatus
import com.tangem.tap.network.exchangeServices.moonpay.models.MoonPayAvailableCurrency import com.tangem.tap.network.exchangeServices.moonpay.models.MoonPayAvailableCurrency
import com.tangem.utils.Provider
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import timber.log.Timber import timber.log.Timber
@ -28,8 +27,8 @@ import javax.crypto.spec.SecretKeySpec
class MoonPayService( class MoonPayService(
private val api: MoonPayApi, private val api: MoonPayApi,
private val apiKeyProvider: Provider<String>, private val apiKey: String,
private val secretKeyProvider: Provider<String>, private val secretKey: String,
private val userWalletProvider: () -> UserWallet?, private val userWalletProvider: () -> UserWallet?,
) : SellService { ) : SellService {
@ -47,18 +46,18 @@ class MoonPayService(
_initializationStatus.value = lceLoading() _initializationStatus.value = lceLoading()
performRequest { performRequest {
val userStatus = when (val result = performRequest { api.getUserStatus(apiKeyProvider()) }) { val userStatus = when (val result = performRequest { api.getUserStatus(apiKey) }) {
is Result.Failure -> { is Result.Failure -> {
Timber.e("Failed to load user status", result.error) Timber.e(result.error, "Failed to load user status")
_initializationStatus.value = result.error.lceError() _initializationStatus.value = result.error.lceError()
return@performRequest return@performRequest
} }
is Result.Success -> result.data is Result.Success -> result.data
} }
val currencies = when (val result = performRequest { api.getCurrencies(apiKeyProvider()) }) { val currencies = when (val result = performRequest { api.getCurrencies(apiKey) }) {
is Result.Failure -> { is Result.Failure -> {
Timber.e("Failed to load currencies", result.error) Timber.e(result.error, "Failed to load currencies")
_initializationStatus.value = result.error.lceError() _initializationStatus.value = result.error.lceError()
return@performRequest return@performRequest
} }
@ -163,7 +162,7 @@ class MoonPayService(
val uri = Uri.Builder() val uri = Uri.Builder()
.scheme(SCHEME) .scheme(SCHEME)
.authority(URL_SELL) .authority(URL_SELL)
.appendQueryParameter("apiKey", apiKeyProvider()) .appendQueryParameter("apiKey", apiKey)
.appendQueryParameter("baseCurrencyCode", moonpayCurrency.currencyCode.uppercase()) .appendQueryParameter("baseCurrencyCode", moonpayCurrency.currencyCode.uppercase())
.appendQueryParameter("refundWalletAddress", walletAddress) .appendQueryParameter("refundWalletAddress", walletAddress)
.appendQueryParameter("redirectURL", "tangem://redirect_sell?currency_id=${cryptoCurrency.id.value}") .appendQueryParameter("redirectURL", "tangem://redirect_sell?currency_id=${cryptoCurrency.id.value}")
@ -179,7 +178,7 @@ class MoonPayService(
private fun createSignature(data: String): String { private fun createSignature(data: String): String {
val sha256Hmac = Mac.getInstance("HmacSHA256") val sha256Hmac = Mac.getInstance("HmacSHA256")
val secretKey = SecretKeySpec(secretKeyProvider().toByteArray(), "HmacSHA256") val secretKey = SecretKeySpec(secretKey.toByteArray(), "HmacSHA256")
sha256Hmac.init(secretKey) sha256Hmac.init(secretKey)
val sha256encoded = sha256Hmac.doFinal("?$data".toByteArray()) val sha256encoded = sha256Hmac.doFinal("?$data".toByteArray())
return Base64.encodeToString(sha256encoded, Base64.NO_WRAP) return Base64.encodeToString(sha256encoded, Base64.NO_WRAP)

View file

@ -11,7 +11,6 @@ import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.data.card.TransactionSignerFactory import com.tangem.data.card.TransactionSignerFactory
import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.token.UserTokensResponseStore
@ -63,7 +62,6 @@ data class DaggerGraphState(
val shareManager: ShareManager? = null, val shareManager: ShareManager? = null,
val appRouter: AppRouter? = null, val appRouter: AppRouter? = null,
val transactionSignerFactory: TransactionSignerFactory? = null, val transactionSignerFactory: TransactionSignerFactory? = null,
val environmentConfigStorage: EnvironmentConfigStorage? = null,
val onboardingV2FeatureToggles: OnboardingV2FeatureToggles? = null, val onboardingV2FeatureToggles: OnboardingV2FeatureToggles? = null,
val onboardingRepository: OnboardingRepository? = null, val onboardingRepository: OnboardingRepository? = null,
val excludedBlockchains: ExcludedBlockchains? = null, val excludedBlockchains: ExcludedBlockchains? = null,

View file

@ -5,8 +5,7 @@ import com.tangem.core.abtests.BuildConfig
import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.abtests.manager.ABTestsManager
import com.tangem.core.abtests.manager.impl.AmplitudeABTestsManager import com.tangem.core.abtests.manager.impl.AmplitudeABTestsManager
import com.tangem.core.abtests.manager.impl.StubABTestsManager import com.tangem.core.abtests.manager.impl.StubABTestsManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -24,7 +23,7 @@ internal object ABTestsManagerModule {
@Singleton @Singleton
fun provideABTestsManager( fun provideABTestsManager(
application: Application, application: Application,
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
dispatchers: CoroutineDispatcherProvider, dispatchers: CoroutineDispatcherProvider,
): ABTestsManager { ): ABTestsManager {
return if (BuildConfig.AB_TESTS_ENABLED) { return if (BuildConfig.AB_TESTS_ENABLED) {
@ -32,7 +31,7 @@ internal object ABTestsManagerModule {
} else { } else {
AmplitudeABTestsManager( AmplitudeABTestsManager(
application = application, application = application,
apiKeyProvider = Provider { environmentConfigStorage.getConfigSync().amplitudeApiKey }, apiKey = environmentConfig.amplitudeApiKey,
scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), scope = CoroutineScope(context = dispatchers.io + SupervisorJob()),
) )
} }

View file

@ -7,14 +7,13 @@ import com.amplitude.experiment.ExperimentConfig
import com.amplitude.experiment.ExperimentUser import com.amplitude.experiment.ExperimentUser
import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.abtests.manager.ABTestsManager
import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.utils.Provider
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
internal class AmplitudeABTestsManager( internal class AmplitudeABTestsManager(
val application: Application, val application: Application,
val apiKeyProvider: Provider<String>, val apiKey: String,
val scope: CoroutineScope, val scope: CoroutineScope,
) : ABTestsManager { ) : ABTestsManager {
@ -28,7 +27,7 @@ internal class AmplitudeABTestsManager(
client = Experiment.initializeWithAmplitudeAnalytics( client = Experiment.initializeWithAmplitudeAnalytics(
application = application, application = application,
apiKey = apiKeyProvider(), apiKey = apiKey,
config = ExperimentConfig config = ExperimentConfig
.builder() .builder()
.automaticFetchOnAmplitudeIdentityChange(true) .automaticFetchOnAmplitudeIdentityChange(true)

View file

@ -1,11 +1,10 @@
package com.tangem.datasource.api.common.config package com.tangem.datasource.api.common.config
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.utils.ProviderSuspend import com.tangem.utils.ProviderSuspend
import kotlinx.coroutines.flow.first
internal class BlockAid( internal class BlockAid(
private val configStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
) : ApiConfig() { ) : ApiConfig() {
override val defaultEnvironment: ApiEnvironment = ApiEnvironment.PROD override val defaultEnvironment: ApiEnvironment = ApiEnvironment.PROD
@ -21,9 +20,7 @@ internal class BlockAid(
put( put(
key = "X-API-KEY", key = "X-API-KEY",
value = ProviderSuspend { value = ProviderSuspend {
requireNotNull( requireNotNull(environmentConfig.blockAidApiKey)
configStorage.getConfig().first { !it.blockAidApiKey.isNullOrEmpty() }.blockAidApiKey,
)
}, },
) )
put("accept", ProviderSuspend { "application/json" }) put("accept", ProviderSuspend { "application/json" })

View file

@ -1,7 +1,7 @@
package com.tangem.datasource.api.common.config package com.tangem.datasource.api.common.config
import com.tangem.datasource.BuildConfig import com.tangem.datasource.BuildConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.utils.RequestHeader import com.tangem.datasource.utils.RequestHeader
import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.ExpressAuthProvider
import com.tangem.utils.ProviderSuspend import com.tangem.utils.ProviderSuspend
@ -11,13 +11,13 @@ import com.tangem.utils.version.AppVersionProvider
/** /**
* Express [ApiConfig] * Express [ApiConfig]
* *
* @property environmentConfigStorage environment config storage * @property environmentConfig environment config
* @property expressAuthProvider express auth provider * @property expressAuthProvider express auth provider
* @property appVersionProvider app version provider * @property appVersionProvider app version provider
* @property appInfoProvider app info provider * @property appInfoProvider app info provider
*/ */
internal class Express( internal class Express(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
private val expressAuthProvider: ExpressAuthProvider, private val expressAuthProvider: ExpressAuthProvider,
private val appVersionProvider: AppVersionProvider, private val appVersionProvider: AppVersionProvider,
private val appInfoProvider: AppInfoProvider, private val appInfoProvider: AppInfoProvider,
@ -100,9 +100,9 @@ internal class Express(
private fun getApiKey(isProd: Boolean): String { private fun getApiKey(isProd: Boolean): String {
return if (isProd) { return if (isProd) {
environmentConfigStorage.getConfigSync().express environmentConfig.express
} else { } else {
environmentConfigStorage.getConfigSync().devExpress environmentConfig.devExpress
} }
?.apiKey ?.apiKey
?: error("No express config provided") ?: error("No express config provided")

View file

@ -1,13 +1,13 @@
package com.tangem.datasource.api.common.config package com.tangem.datasource.api.common.config
import com.tangem.datasource.BuildConfig import com.tangem.datasource.BuildConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.utils.ProviderSuspend import com.tangem.utils.ProviderSuspend
import com.tangem.utils.version.AppVersionProvider import com.tangem.utils.version.AppVersionProvider
internal sealed class TangemPay( internal sealed class TangemPay(
private val environmentConfig: EnvironmentConfig,
private val appVersionProvider: AppVersionProvider, private val appVersionProvider: AppVersionProvider,
private val environmentConfigStorage: EnvironmentConfigStorage,
) : ApiConfig() { ) : ApiConfig() {
override val defaultEnvironment: ApiEnvironment = getInitialEnvironment() override val defaultEnvironment: ApiEnvironment = getInitialEnvironment()
@ -61,8 +61,8 @@ internal sealed class TangemPay(
return when (apiEnvironment) { return when (apiEnvironment) {
ApiEnvironment.MOCK, ApiEnvironment.MOCK,
ApiEnvironment.DEV, ApiEnvironment.DEV,
-> environmentConfigStorage.getConfigSync().bffStaticTokenDev -> environmentConfig.bffStaticTokenDev
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().bffStaticToken ApiEnvironment.PROD -> environmentConfig.bffStaticToken
ApiEnvironment.STAGE, ApiEnvironment.STAGE,
ApiEnvironment.STAGE_2, ApiEnvironment.STAGE_2,
ApiEnvironment.DEV_2, ApiEnvironment.DEV_2,
@ -72,9 +72,9 @@ internal sealed class TangemPay(
} }
class Bff( class Bff(
environmentConfig: EnvironmentConfig,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
environmentConfigStorage: EnvironmentConfigStorage, ) : TangemPay(environmentConfig, appVersionProvider) {
) : TangemPay(appVersionProvider, environmentConfigStorage) {
override fun getBaseUrl(apiEnvironment: ApiEnvironment): String { override fun getBaseUrl(apiEnvironment: ApiEnvironment): String {
return when (apiEnvironment) { return when (apiEnvironment) {
ApiEnvironment.DEV -> "https://api.dev.us.paera.com/bff-v2/" ApiEnvironment.DEV -> "https://api.dev.us.paera.com/bff-v2/"
@ -90,9 +90,9 @@ internal sealed class TangemPay(
} }
class Auth( class Auth(
environmentConfig: EnvironmentConfig,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
environmentConfigStorage: EnvironmentConfigStorage, ) : TangemPay(environmentConfig, appVersionProvider) {
) : TangemPay(appVersionProvider, environmentConfigStorage) {
override fun getBaseUrl(apiEnvironment: ApiEnvironment): String { override fun getBaseUrl(apiEnvironment: ApiEnvironment): String {
return when (apiEnvironment) { return when (apiEnvironment) {
ApiEnvironment.DEV -> "https://api.dev.us.paera.com/" ApiEnvironment.DEV -> "https://api.dev.us.paera.com/"

View file

@ -2,7 +2,7 @@ package com.tangem.datasource.api.common.config
import com.tangem.datasource.BuildConfig import com.tangem.datasource.BuildConfig
import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.utils.RequestHeader import com.tangem.datasource.utils.RequestHeader
import com.tangem.utils.ProviderSuspend import com.tangem.utils.ProviderSuspend
import com.tangem.utils.info.AppInfoProvider import com.tangem.utils.info.AppInfoProvider
@ -10,7 +10,7 @@ import com.tangem.utils.version.AppVersionProvider
/** YieldSupply [ApiConfig] */ /** YieldSupply [ApiConfig] */
internal class YieldSupply( internal class YieldSupply(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
private val appVersionProvider: AppVersionProvider, private val appVersionProvider: AppVersionProvider,
private val authProvider: AuthProvider, private val authProvider: AuthProvider,
private val appInfoProvider: AppInfoProvider, private val appInfoProvider: AppInfoProvider,
@ -78,8 +78,8 @@ internal class YieldSupply(
ApiEnvironment.DEV_3, ApiEnvironment.DEV_3,
ApiEnvironment.STAGE, ApiEnvironment.STAGE,
ApiEnvironment.STAGE_2, ApiEnvironment.STAGE_2,
-> environmentConfigStorage.getConfigSync().yieldModuleApiKeyDev -> environmentConfig.yieldModuleApiKeyDev
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().yieldModuleApiKey ApiEnvironment.PROD -> environmentConfig.yieldModuleApiKey
} ?: error("No tangem tech api config provided") } ?: error("No tangem tech api config provided")
} }
} }

View file

@ -5,10 +5,10 @@ import com.tangem.crypto.CryptoUtils
import com.tangem.datasource.api.common.config.ApiConfig import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiEnvironment 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.ApiConfigsManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
internal class Sha256SignatureVerifier( internal class Sha256SignatureVerifier(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
private val apiConfigsManager: ApiConfigsManager, private val apiConfigsManager: ApiConfigsManager,
) : DataSignatureVerifier { ) : DataSignatureVerifier {
@ -24,8 +24,8 @@ internal class Sha256SignatureVerifier(
private fun getPubKey(): String? { private fun getPubKey(): String? {
val expressConfig = apiConfigsManager.getEnvironmentConfig(ApiConfig.ID.Express) val expressConfig = apiConfigsManager.getEnvironmentConfig(ApiConfig.ID.Express)
return when (expressConfig.environment) { return when (expressConfig.environment) {
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().express?.signVerifierPublicKey ApiEnvironment.PROD -> environmentConfig.express?.signVerifierPublicKey
else -> environmentConfigStorage.getConfigSync().devExpress?.signVerifierPublicKey else -> environmentConfig.devExpress?.signVerifierPublicKey
} }
} }
} }

View file

@ -2,7 +2,7 @@ package com.tangem.datasource.di
import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.api.common.config.* import com.tangem.datasource.api.common.config.*
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.ExpressAuthProvider
import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.lib.auth.P2PEthPoolAuthProvider
import com.tangem.lib.auth.StakeKitAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider
@ -21,13 +21,13 @@ internal object ApiConfigsModule {
@Provides @Provides
@IntoSet @IntoSet
fun provideExpressConfig( fun provideExpressConfig(
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
expressAuthProvider: ExpressAuthProvider, expressAuthProvider: ExpressAuthProvider,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
appInfoProvider: AppInfoProvider, appInfoProvider: AppInfoProvider,
): ApiConfig { ): ApiConfig {
return Express( return Express(
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
expressAuthProvider = expressAuthProvider, expressAuthProvider = expressAuthProvider,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
appInfoProvider = appInfoProvider, appInfoProvider = appInfoProvider,
@ -73,12 +73,12 @@ internal object ApiConfigsModule {
@Provides @Provides
@IntoSet @IntoSet
fun provideYieldSupplyConfig( fun provideYieldSupplyConfig(
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
authProvider: AuthProvider, authProvider: AuthProvider,
appInfoProvider: AppInfoProvider, appInfoProvider: AppInfoProvider,
): ApiConfig = YieldSupply( ): ApiConfig = YieldSupply(
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
authProvider = authProvider, authProvider = authProvider,
appInfoProvider = appInfoProvider, appInfoProvider = appInfoProvider,
@ -87,21 +87,21 @@ internal object ApiConfigsModule {
@Provides @Provides
@IntoSet @IntoSet
fun provideTangemPayBffConfig( fun provideTangemPayBffConfig(
environmentConfig: EnvironmentConfig,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
environmentConfigStorage: EnvironmentConfigStorage, ): ApiConfig = TangemPay.Bff(environmentConfig, appVersionProvider)
): ApiConfig = TangemPay.Bff(appVersionProvider, environmentConfigStorage)
@Provides @Provides
@IntoSet @IntoSet
fun provideTangemPayAuthConfig( fun provideTangemPayAuthConfig(
environmentConfig: EnvironmentConfig,
appVersionProvider: AppVersionProvider, appVersionProvider: AppVersionProvider,
environmentConfigStorage: EnvironmentConfigStorage, ): ApiConfig = TangemPay.Auth(environmentConfig, appVersionProvider)
): ApiConfig = TangemPay.Auth(appVersionProvider, environmentConfigStorage)
@Provides @Provides
@IntoSet @IntoSet
fun provideBlockAidConfig(environmentConfigStorage: EnvironmentConfigStorage): ApiConfig { fun provideBlockAidConfig(environmentConfig: EnvironmentConfig): ApiConfig {
return BlockAid(environmentConfigStorage) return BlockAid(environmentConfig)
} }
@Provides @Provides

View file

@ -3,7 +3,7 @@ package com.tangem.datasource.di
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.crypto.DataSignatureVerifier import com.tangem.datasource.crypto.DataSignatureVerifier
import com.tangem.datasource.crypto.Sha256SignatureVerifier import com.tangem.datasource.crypto.Sha256SignatureVerifier
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -17,9 +17,9 @@ internal object SecurityModule {
@Provides @Provides
@Singleton @Singleton
fun provideDataSignatureVerifier( fun provideDataSignatureVerifier(
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
apiConfigsManager: ApiConfigsManager, apiConfigsManager: ApiConfigsManager,
): DataSignatureVerifier { ): DataSignatureVerifier {
return Sha256SignatureVerifier(environmentConfigStorage, apiConfigsManager) return Sha256SignatureVerifier(environmentConfig, apiConfigsManager)
} }
} }

View file

@ -1,9 +1,8 @@
package com.tangem.datasource.di.local.config package com.tangem.datasource.di.local.config
import com.tangem.datasource.asset.loader.AssetLoader import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.local.config.environment.DefaultEnvironmentConfigStorage
import com.tangem.datasource.local.config.environment.EnvironmentConfig import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.converter.GeneratedEnvironmentConfigConverter
import com.tangem.datasource.local.config.issuers.DefaultIssuersConfigStorage import com.tangem.datasource.local.config.issuers.DefaultIssuersConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.config.providers.BlockchainProvidersStorage import com.tangem.datasource.local.config.providers.BlockchainProvidersStorage
@ -23,11 +22,8 @@ internal object ConfigModule {
@Provides @Provides
@Singleton @Singleton
fun provideEnvironmentConfigStorage(assetLoader: AssetLoader): EnvironmentConfigStorage { fun provideEnvironmentConfig(): EnvironmentConfig {
return DefaultEnvironmentConfigStorage( return GeneratedEnvironmentConfigConverter.convert()
assetLoader = assetLoader,
environmentConfigStore = RuntimeStateStore(defaultValue = EnvironmentConfig()),
)
} }
@Provides @Provides

View file

@ -1,41 +0,0 @@
package com.tangem.datasource.local.config.environment
import com.tangem.datasource.BuildConfig
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.local.config.environment.converter.EnvironmentConfigConverter
import com.tangem.datasource.local.config.environment.models.EnvironmentConfigModel
import com.tangem.datasource.local.datastore.RuntimeStateStore
import kotlinx.coroutines.flow.Flow
import timber.log.Timber
/**
* Default implementation for storing [EnvironmentConfig]
*
* @property assetLoader asset loader
* @property environmentConfigStore config store
*/
internal class DefaultEnvironmentConfigStorage(
private val assetLoader: AssetLoader,
private val environmentConfigStore: RuntimeStateStore<EnvironmentConfig>,
) : EnvironmentConfigStorage {
override suspend fun initialize(): EnvironmentConfig {
val environmentConfigModel = assetLoader.load<EnvironmentConfigModel>(fileName = CONFIG_FILE_NAME)
?: return environmentConfigStore.get().value
val config = EnvironmentConfigConverter.convert(value = environmentConfigModel)
environmentConfigStore.store(value = config)
Timber.i("Config [$CONFIG_FILE_NAME] loaded successfully")
return config
}
override fun getConfig(): Flow<EnvironmentConfig> = environmentConfigStore.get()
override fun getConfigSync(): EnvironmentConfig = environmentConfigStore.get().value
private companion object {
const val CONFIG_FILE_NAME = "tangem-app-config/config_${BuildConfig.ENVIRONMENT}"
}
}

View file

@ -1,20 +0,0 @@
package com.tangem.datasource.local.config.environment
import kotlinx.coroutines.flow.Flow
/**
* Storage for [EnvironmentConfig]
*
[REDACTED_AUTHOR]
*/
interface EnvironmentConfigStorage {
/** Initialize and return [EnvironmentConfig] */
suspend fun initialize(): EnvironmentConfig
/** Get [EnvironmentConfig] as [Flow] */
fun getConfig(): Flow<EnvironmentConfig>
/** Get [EnvironmentConfig] synchronously */
fun getConfigSync(): EnvironmentConfig
}

View file

@ -2,6 +2,7 @@ package com.tangem.datasource.api.common.config
import com.google.common.truth.Truth import com.google.common.truth.Truth
import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.utils.ProviderSuspend import com.tangem.utils.ProviderSuspend
import io.mockk.clearMocks import io.mockk.clearMocks
import io.mockk.every import io.mockk.every
@ -19,6 +20,7 @@ class ApiConfigTest {
private val appAuthProvider = mockk<AuthProvider>() private val appAuthProvider = mockk<AuthProvider>()
private val apiKeyProvider = mockk<ProviderSuspend<String>>() private val apiKeyProvider = mockk<ProviderSuspend<String>>()
private val environmentConfig = mockk<EnvironmentConfig>()
@BeforeEach @BeforeEach
fun setup() { fun setup() {
@ -47,7 +49,7 @@ class ApiConfigTest {
when (it) { when (it) {
ApiConfig.ID.Express -> { ApiConfig.ID.Express -> {
Express( Express(
environmentConfigStorage = mockk(), environmentConfig = environmentConfig,
expressAuthProvider = mockk(), expressAuthProvider = mockk(),
appVersionProvider = mockk(), appVersionProvider = mockk(),
appInfoProvider = mockk(), appInfoProvider = mockk(),
@ -55,7 +57,7 @@ class ApiConfigTest {
} }
ApiConfig.ID.YieldSupply -> { ApiConfig.ID.YieldSupply -> {
YieldSupply( YieldSupply(
environmentConfigStorage = mockk(), environmentConfig = environmentConfig,
appVersionProvider = mockk(), appVersionProvider = mockk(),
authProvider = appAuthProvider, authProvider = appAuthProvider,
appInfoProvider = mockk(), appInfoProvider = mockk(),
@ -70,14 +72,14 @@ class ApiConfigTest {
} }
ApiConfig.ID.StakeKit -> StakeKit(stakeKitAuthProvider = mockk()) ApiConfig.ID.StakeKit -> StakeKit(stakeKitAuthProvider = mockk())
ApiConfig.ID.TangemPay -> TangemPay.Bff( ApiConfig.ID.TangemPay -> TangemPay.Bff(
environmentConfig = environmentConfig,
appVersionProvider = mockk(), appVersionProvider = mockk(),
environmentConfigStorage = mockk()
) )
ApiConfig.ID.TangemPayAuth -> TangemPay.Auth( ApiConfig.ID.TangemPayAuth -> TangemPay.Auth(
environmentConfig = environmentConfig,
appVersionProvider = mockk(), appVersionProvider = mockk(),
environmentConfigStorage = mockk()
) )
ApiConfig.ID.BlockAid -> BlockAid(configStorage = mockk()) ApiConfig.ID.BlockAid -> BlockAid(environmentConfig = environmentConfig)
ApiConfig.ID.MoonPay -> MoonPay() ApiConfig.ID.MoonPay -> MoonPay()
ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = mockk()) ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = mockk())
ApiConfig.ID.News -> News( ApiConfig.ID.News -> News(

View file

@ -1,45 +0,0 @@
package com.tangem.datasource.api.common.config.managers
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.environment.models.ExpressModel
import kotlinx.coroutines.flow.flowOf
/**
* Mock [EnvironmentConfigStorage] implementation for [ProdApiConfigsManagerTest]
*
[REDACTED_AUTHOR]
*/
internal class MockEnvironmentConfigStorage : EnvironmentConfigStorage {
private val environmentConfig = EnvironmentConfig(
express = ExpressModel(apiKey = EXPRESS_API_KEY, signVerifierPublicKey = "vocibus"),
devExpress = ExpressModel(apiKey = EXPRESS_DEV_API_KEY, signVerifierPublicKey = "pellentesque"),
blockAidApiKey = BLOCK_AID_API_KEY,
tangemApiKey = TANGEM_API_KEY,
tangemApiKeyDev = TANGEM_API_KEY_DEV,
bffStaticToken = TANGEM_PAY_BFF_KEY,
bffStaticTokenDev = TANGEM_PAY_BFF_KEY_DEV,
tangemApiKeyStage = TANGEM_API_KEY_STAGE,
yieldModuleApiKey = YIELD_MODULE_KEY,
yieldModuleApiKeyDev = YIELD_MODULE_KEY_DEV,
)
override suspend fun initialize() = environmentConfig
override fun getConfig() = flowOf(environmentConfig)
override fun getConfigSync() = environmentConfig
companion object {
const val EXPRESS_API_KEY = "express_api_key"
const val EXPRESS_DEV_API_KEY = "express_dev_api_key"
const val BLOCK_AID_API_KEY = "block_aid_api_key"
const val TANGEM_API_KEY = "tangem_api_key"
const val TANGEM_API_KEY_DEV = "tangem_api_key_dev"
const val TANGEM_PAY_BFF_KEY = "tangem_pay_bff_key"
const val TANGEM_PAY_BFF_KEY_DEV = "tangem_pay_bff_key_dev"
const val TANGEM_GASLESS_API_KEY = "tangem_gasless_api_key"
const val TANGEM_API_KEY_STAGE = "tangem_api_key_stage"
const val YIELD_MODULE_KEY = "yield_module_api_key"
const val YIELD_MODULE_KEY_DEV = "yield_module_api_key_dev"
}
}

View file

@ -10,10 +10,8 @@ import com.tangem.datasource.api.common.config.ApiConfig.Companion.EXTERNAL_BUIL
import com.tangem.datasource.api.common.config.ApiConfig.Companion.INTERNAL_BUILD_TYPE import com.tangem.datasource.api.common.config.ApiConfig.Companion.INTERNAL_BUILD_TYPE
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.BLOCK_AID_API_KEY import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_API_KEY import com.tangem.datasource.local.config.environment.models.ExpressModel
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_GASLESS_API_KEY
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_PAY_BFF_KEY_DEV
import com.tangem.domain.staking.model.ethpool.P2PEthPoolStakingConfig import com.tangem.domain.staking.model.ethpool.P2PEthPoolStakingConfig
import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.ExpressAuthProvider
import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.lib.auth.P2PEthPoolAuthProvider
@ -39,7 +37,7 @@ import java.util.TimeZone
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class ProdApiConfigsManagerTest { internal class ProdApiConfigsManagerTest {
private val environmentConfigStorage = MockEnvironmentConfigStorage() private val environmentConfig = createMockEnvironmentConfig()
private val appVersionProvider = mockk<AppVersionProvider>() private val appVersionProvider = mockk<AppVersionProvider>()
private val expressAuthProvider = mockk<ExpressAuthProvider>() private val expressAuthProvider = mockk<ExpressAuthProvider>()
private val stakeKitAuthProvider = mockk<StakeKitAuthProvider>() private val stakeKitAuthProvider = mockk<StakeKitAuthProvider>()
@ -94,7 +92,7 @@ internal class ProdApiConfigsManagerTest {
when (it) { when (it) {
ApiConfig.ID.Express -> { ApiConfig.ID.Express -> {
Express( Express(
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
expressAuthProvider = expressAuthProvider, expressAuthProvider = expressAuthProvider,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
appInfoProvider = appInfoProvider, appInfoProvider = appInfoProvider,
@ -102,7 +100,7 @@ internal class ProdApiConfigsManagerTest {
} }
ApiConfig.ID.YieldSupply -> { ApiConfig.ID.YieldSupply -> {
YieldSupply( YieldSupply(
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
authProvider = appAuthProvider, authProvider = appAuthProvider,
appInfoProvider = appInfoProvider, appInfoProvider = appInfoProvider,
@ -117,14 +115,14 @@ internal class ProdApiConfigsManagerTest {
} }
ApiConfig.ID.StakeKit -> StakeKit(stakeKitAuthProvider = stakeKitAuthProvider) ApiConfig.ID.StakeKit -> StakeKit(stakeKitAuthProvider = stakeKitAuthProvider)
ApiConfig.ID.TangemPay -> TangemPay.Bff( ApiConfig.ID.TangemPay -> TangemPay.Bff(
environmentConfig = environmentConfig,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
environmentConfigStorage = environmentConfigStorage,
) )
ApiConfig.ID.TangemPayAuth -> TangemPay.Auth( ApiConfig.ID.TangemPayAuth -> TangemPay.Auth(
environmentConfig = environmentConfig,
appVersionProvider = appVersionProvider, appVersionProvider = appVersionProvider,
environmentConfigStorage = environmentConfigStorage,
) )
ApiConfig.ID.BlockAid -> BlockAid(configStorage = environmentConfigStorage) ApiConfig.ID.BlockAid -> BlockAid(environmentConfig = environmentConfig)
ApiConfig.ID.MoonPay -> MoonPay() ApiConfig.ID.MoonPay -> MoonPay()
ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = p2pEthPoolAuthProvider) ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = p2pEthPoolAuthProvider)
ApiConfig.ID.News -> News( ApiConfig.ID.News -> News(
@ -188,9 +186,9 @@ internal class ProdApiConfigsManagerTest {
headers = mapOf( headers = mapOf(
"api-key" to ProviderSuspend { "api-key" to ProviderSuspend {
if (environment == ApiEnvironment.PROD) { if (environment == ApiEnvironment.PROD) {
MockEnvironmentConfigStorage.EXPRESS_API_KEY EXPRESS_API_KEY
} else { } else {
MockEnvironmentConfigStorage.EXPRESS_DEV_API_KEY EXPRESS_DEV_API_KEY
} }
}, },
"session-id" to ProviderSuspend { EXPRESS_SESSION_ID }, "session-id" to ProviderSuspend { EXPRESS_SESSION_ID },
@ -237,7 +235,7 @@ internal class ProdApiConfigsManagerTest {
environment = ApiEnvironment.PROD, environment = ApiEnvironment.PROD,
baseUrl = "https://yield.tangem.org/", baseUrl = "https://yield.tangem.org/",
headers = mapOf( headers = mapOf(
"api-key" to ProviderSuspend { MockEnvironmentConfigStorage.YIELD_MODULE_KEY }, "api-key" to ProviderSuspend { YIELD_MODULE_KEY },
"card_id" to ProviderSuspend { APP_CARD_ID }, "card_id" to ProviderSuspend { APP_CARD_ID },
"card_public_key" to ProviderSuspend { APP_CARD_PUBLIC_KEY }, "card_public_key" to ProviderSuspend { APP_CARD_PUBLIC_KEY },
"version" to ProviderSuspend { VERSION_NAME }, "version" to ProviderSuspend { VERSION_NAME },
@ -426,5 +424,48 @@ internal class ProdApiConfigsManagerTest {
const val P2P_API_KEY = "p2p_api_key" const val P2P_API_KEY = "p2p_api_key"
const val APP_CARD_ID = "app_card_id" const val APP_CARD_ID = "app_card_id"
const val APP_CARD_PUBLIC_KEY = "Bearer app_public_key" const val APP_CARD_PUBLIC_KEY = "Bearer app_public_key"
// Mock config values
const val TANGEM_API_KEY = "tangem_api_key"
const val TANGEM_GASLESS_API_KEY = "tangem_gasless_api_key"
const val TANGEM_PAY_BFF_KEY_DEV = "tangem_pay_bff_key_dev"
const val BLOCK_AID_API_KEY = "block_aid_api_key"
const val EXPRESS_API_KEY = "express_api_key"
const val EXPRESS_DEV_API_KEY = "express_dev_api_key"
const val YIELD_MODULE_KEY = "yield_module_key"
fun createMockEnvironmentConfig(): EnvironmentConfig {
return EnvironmentConfig(
moonPayApiKey = "moon_pay_api_key",
moonPayApiSecretKey = "moon_pay_secret_key",
mercuryoWidgetId = "mercuryo_widget_id",
mercuryoSecret = "mercuryo_secret",
blockchainSdkConfig = mockk(relaxed = true),
amplitudeApiKey = "amplitude_api_key",
appsFlyerApiKey = "appsflyer_api_key",
appsAppId = "apps_app_id",
walletConnectProjectId = "wallet_connect_project_id",
express = ExpressModel(
apiKey = EXPRESS_API_KEY,
signVerifierPublicKey = "express_public_key",
),
devExpress = ExpressModel(
apiKey = EXPRESS_DEV_API_KEY,
signVerifierPublicKey = "express_dev_public_key",
),
stakeKitApiKey = STAKE_KIT_API_KEY,
p2pApiKey = null,
blockAidApiKey = BLOCK_AID_API_KEY,
tangemApiKey = TANGEM_API_KEY,
tangemApiKeyDev = TANGEM_API_KEY,
tangemApiKeyStage = TANGEM_API_KEY,
yieldModuleApiKey = YIELD_MODULE_KEY,
yieldModuleApiKeyDev = YIELD_MODULE_KEY,
bffStaticToken = TANGEM_PAY_BFF_KEY_DEV,
bffStaticTokenDev = TANGEM_PAY_BFF_KEY_DEV,
gaslessTxApiKeyDev = TANGEM_GASLESS_API_KEY,
gaslessTxApiKey = TANGEM_GASLESS_API_KEY,
)
}
} }
} }

View file

@ -18,7 +18,7 @@ import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.datasource.crypto.DataSignatureVerifier import com.tangem.datasource.crypto.DataSignatureVerifier
import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.exchangeservice.hotcrypto.HotCryptoResponseStore import com.tangem.datasource.exchangeservice.hotcrypto.HotCryptoResponseStore
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.onramp.countries.OnrampCountriesStore import com.tangem.datasource.local.onramp.countries.OnrampCountriesStore
import com.tangem.datasource.local.onramp.currencies.OnrampCurrenciesStore import com.tangem.datasource.local.onramp.currencies.OnrampCurrenciesStore
import com.tangem.datasource.local.onramp.pairs.OnrampPairsStore import com.tangem.datasource.local.onramp.pairs.OnrampPairsStore
@ -131,11 +131,11 @@ internal object OnrampDataModule {
@Provides @Provides
@Singleton @Singleton
fun provideMercuryoRepository( fun provideMercuryoRepository(
environmentConfigStorage: EnvironmentConfigStorage, environmentConfig: EnvironmentConfig,
dispatchersProvider: CoroutineDispatcherProvider, dispatchersProvider: CoroutineDispatcherProvider,
): LegacyTopUpRepository { ): LegacyTopUpRepository {
return MercuryoTopUpRepository( return MercuryoTopUpRepository(
environmentConfigStorage = environmentConfigStorage, environmentConfig = environmentConfig,
dispatchersProvider = dispatchersProvider, dispatchersProvider = dispatchersProvider,
) )
} }

View file

@ -5,7 +5,6 @@ import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.common.extensions.calculateSha512 import com.tangem.common.extensions.calculateSha512
import com.tangem.common.extensions.toHexString import com.tangem.common.extensions.toHexString
import com.tangem.datasource.local.config.environment.EnvironmentConfig import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.onramp.repositories.LegacyTopUpRepository import com.tangem.domain.onramp.repositories.LegacyTopUpRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -13,14 +12,13 @@ import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
internal class MercuryoTopUpRepository @Inject constructor( internal class MercuryoTopUpRepository @Inject constructor(
private val environmentConfigStorage: EnvironmentConfigStorage, private val environmentConfig: EnvironmentConfig,
private val dispatchersProvider: CoroutineDispatcherProvider, private val dispatchersProvider: CoroutineDispatcherProvider,
) : LegacyTopUpRepository { ) : LegacyTopUpRepository {
override suspend fun getTopUpUrl(cryptoCurrency: CryptoCurrency, walletAddress: String): String = override suspend fun getTopUpUrl(cryptoCurrency: CryptoCurrency, walletAddress: String): String =
withContext(dispatchersProvider.default) { withContext(dispatchersProvider.default) {
val blockchain = cryptoCurrency.network.toBlockchain() val blockchain = cryptoCurrency.network.toBlockchain()
val environmentConfig = environmentConfigStorage.getConfigSync()
val builder = Uri.Builder() val builder = Uri.Builder()
.scheme(LegacyTopUpRepository.SCHEME) .scheme(LegacyTopUpRepository.SCHEME)

View file

@ -1,8 +1,8 @@
package com.tangem.blockchainsdk package com.tangem.blockchainsdk
import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.blockchainsdk.providers.BlockchainProvidersTypesManager import com.tangem.blockchainsdk.providers.BlockchainProvidersTypesManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.providers.models.ProviderModel import com.tangem.datasource.local.config.providers.models.ProviderModel
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -15,16 +15,16 @@ internal typealias BlockchainProvidersResponse = Map<String, List<ProviderModel>
/** /**
* Implementation of Blockchain SDK components factory * Implementation of Blockchain SDK components factory
* *
* @property blockchainSdkConfig blockchain SDK config
* @property blockchainProvidersTypesManager blockchain providers types manager * @property blockchainProvidersTypesManager blockchain providers types manager
* @property environmentConfigStorage environment config storage
* @property walletManagerFactoryCreator wallet manager factory creator * @property walletManagerFactoryCreator wallet manager factory creator
* @param dispatchers coroutine dispatchers provider * @param dispatchers coroutine dispatchers provider
* *
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
internal class DefaultBlockchainSDKFactory( internal class DefaultBlockchainSDKFactory(
private val blockchainSdkConfig: BlockchainSdkConfig,
private val blockchainProvidersTypesManager: BlockchainProvidersTypesManager, private val blockchainProvidersTypesManager: BlockchainProvidersTypesManager,
private val environmentConfigStorage: EnvironmentConfigStorage,
private val walletManagerFactoryCreator: WalletManagerFactoryCreator, private val walletManagerFactoryCreator: WalletManagerFactoryCreator,
dispatchers: CoroutineDispatcherProvider, dispatchers: CoroutineDispatcherProvider,
) : BlockchainSDKFactory { ) : BlockchainSDKFactory {
@ -43,7 +43,7 @@ internal class DefaultBlockchainSDKFactory(
private fun createWalletManagerFactory(): Flow<WalletManagerFactory?> { private fun createWalletManagerFactory(): Flow<WalletManagerFactory?> {
return combine( return combine(
flow = environmentConfigStorage.getConfig().map { it.blockchainSdkConfig }, flow = flowOf(blockchainSdkConfig),
flow2 = blockchainProvidersTypesManager.get(), flow2 = blockchainProvidersTypesManager.get(),
// flow3 = subscribe on feature toggles changes, TODO: [REDACTED_JIRA] // flow3 = subscribe on feature toggles changes, TODO: [REDACTED_JIRA]
transform = walletManagerFactoryCreator::create, transform = walletManagerFactoryCreator::create,

View file

@ -19,7 +19,7 @@ import com.tangem.blockchainsdk.providers.ProdBlockchainProvidersTypesManager
import com.tangem.blockchainsdk.providers.dev.BlockchainProvidersResponseSerializer import com.tangem.blockchainsdk.providers.dev.BlockchainProvidersResponseSerializer
import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.libs.blockchain_sdk.BuildConfig import com.tangem.libs.blockchain_sdk.BuildConfig
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -39,14 +39,14 @@ internal object BlockchainSDKFactoryModule {
@Provides @Provides
@Singleton @Singleton
fun provideBlockchainSDKFactory( fun provideBlockchainSDKFactory(
environmentConfig: EnvironmentConfig,
blockchainProvidersTypesManager: BlockchainProvidersTypesManager, blockchainProvidersTypesManager: BlockchainProvidersTypesManager,
environmentConfigStorage: EnvironmentConfigStorage,
walletManagerFactoryCreator: WalletManagerFactoryCreator, walletManagerFactoryCreator: WalletManagerFactoryCreator,
dispatchers: CoroutineDispatcherProvider, dispatchers: CoroutineDispatcherProvider,
): BlockchainSDKFactory { ): BlockchainSDKFactory {
return DefaultBlockchainSDKFactory( return DefaultBlockchainSDKFactory(
blockchainSdkConfig = environmentConfig.blockchainSdkConfig,
blockchainProvidersTypesManager = blockchainProvidersTypesManager, blockchainProvidersTypesManager = blockchainProvidersTypesManager,
environmentConfigStorage = environmentConfigStorage,
walletManagerFactoryCreator = walletManagerFactoryCreator, walletManagerFactoryCreator = walletManagerFactoryCreator,
dispatchers = dispatchers, dispatchers = dispatchers,
) )