Updated on 2026-08-14
This commit is contained in:
parent
c5a596d7fc
commit
f388510170
13 changed files with 198 additions and 107 deletions
|
|
@ -16,7 +16,9 @@ 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.ApiEnvironmentConfig
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.datasource.api.common.config.managers.MutableApiConfigsManager
|
||||
import com.tangem.datasource.utils.AddHeadersInterceptor
|
||||
import com.tangem.datasource.utils.RequestHeader
|
||||
import com.tangem.operations.attestation.api.TangemApiServiceSettings
|
||||
|
|
@ -56,28 +58,15 @@ internal class DefaultCardSdkProvider @Inject constructor(
|
|||
get() = holder?.sdk ?: tryToRegisterWithForegroundActivity()
|
||||
|
||||
init {
|
||||
// TODO: [REDACTED_TASK_KEY] Change API's base URL in CardSDK if API environment is changed
|
||||
// if (BuildConfig.TESTER_MENU_ENABLED) {
|
||||
// appPreferencesStore.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
// .map {
|
||||
// when (it[ApiConfig.ID.TangemTech.name]) {
|
||||
// ApiEnvironment.DEV,
|
||||
// ApiEnvironment.STAGE,
|
||||
// ApiEnvironment.MOCK,
|
||||
// -> false
|
||||
// ApiEnvironment.PROD,
|
||||
// null,
|
||||
// -> true
|
||||
// }
|
||||
// }
|
||||
// .distinctUntilChanged()
|
||||
// .onEach { isProd ->
|
||||
// holder?.let {
|
||||
// it.sdk.config.isTangemAttestationProdEnv = isProd
|
||||
// }
|
||||
// }
|
||||
// .launchIn(CoroutineScope(SupervisorJob() + dispatchers.main))
|
||||
// }
|
||||
val mutableManager = apiConfigsManager as? MutableApiConfigsManager
|
||||
|
||||
mutableManager?.addListener(
|
||||
object : MutableApiConfigsManager.ApiConfigEnvChangeListener(id = ApiConfig.ID.TangemTech) {
|
||||
override fun onChange(environmentConfig: ApiEnvironmentConfig) {
|
||||
holder?.sdk?.config?.tangemApiBaseUrl = environmentConfig.baseUrl
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
TangemApiServiceSettings.addInterceptors(
|
||||
AddHeadersInterceptor(
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ internal class TangemTech(
|
|||
|
||||
private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.tangem.org/v1/",
|
||||
baseUrl = "https://api.tangem.org/",
|
||||
headers = createHeaders(),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ internal class DevApiConfigsManager(
|
|||
private val apiConfigs: ApiConfigs,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MutableApiConfigsManager {
|
||||
) : MutableApiConfigsManager() {
|
||||
|
||||
override val configs: StateFlow<Map<ApiConfig, ApiEnvironment>>
|
||||
field = MutableStateFlow(value = getInitialConfigs())
|
||||
|
|
@ -34,22 +34,22 @@ internal class DevApiConfigsManager(
|
|||
override fun initialize() {
|
||||
isInitialized.value = false
|
||||
|
||||
// We can't use appPreferencesStore.getObjectMap as base flow,
|
||||
// because we should keep possibility to work with configs synchronous.
|
||||
// See [getBaseUrl]
|
||||
appPreferencesStore.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
.distinctUntilChanged()
|
||||
.onEach { savedEnvironments ->
|
||||
configs.update { apiConfigs ->
|
||||
apiConfigs.mapValues {
|
||||
val (config, currentEnvironment) = it
|
||||
val apiConfigs = configs.value
|
||||
|
||||
savedEnvironments[config.id.name] ?: currentEnvironment
|
||||
}
|
||||
configs.value = apiConfigs.mapValues {
|
||||
val (config, currentEnvironment) = it
|
||||
|
||||
savedEnvironments[config.id.name] ?: currentEnvironment
|
||||
}
|
||||
|
||||
if (!isInitialized.value) {
|
||||
isInitialized.value = true
|
||||
}
|
||||
|
||||
notifyListeners(apiConfigs = apiConfigs, savedEnvironments = savedEnvironments)
|
||||
}
|
||||
.launchIn(CoroutineScope(SupervisorJob() + dispatchers.default))
|
||||
}
|
||||
|
|
@ -96,6 +96,35 @@ internal class DevApiConfigsManager(
|
|||
}
|
||||
}
|
||||
|
||||
private fun notifyListeners(
|
||||
apiConfigs: Map<ApiConfig, ApiEnvironment>,
|
||||
savedEnvironments: Map<String, ApiEnvironment>,
|
||||
) {
|
||||
if (registerListeners.isNotEmpty()) {
|
||||
val changedConfigs = apiConfigs.mapNotNull { (config, prevEnvironment) ->
|
||||
val newEnvironment = savedEnvironments[config.id.name] ?: config.defaultEnvironment
|
||||
|
||||
if (prevEnvironment == newEnvironment) return@mapNotNull null
|
||||
|
||||
val environmentConfig = config.environmentConfigs
|
||||
.firstOrNull { it.environment == newEnvironment }
|
||||
?: return@mapNotNull null
|
||||
|
||||
config.id to environmentConfig
|
||||
}
|
||||
|
||||
if (changedConfigs.isNotEmpty()) {
|
||||
registerListeners.forEach { listener ->
|
||||
val changedConfig = changedConfigs.firstOrNull { it.first == listener.id }?.second
|
||||
|
||||
if (changedConfig != null) {
|
||||
listener.onChange(changedConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitialConfigs(): Map<ApiConfig, ApiEnvironment> {
|
||||
return apiConfigs.associateWith(ApiConfig::defaultEnvironment)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import com.tangem.datasource.api.common.config.ApiConfig
|
|||
import com.tangem.datasource.api.common.config.ApiConfigs
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironmentConfig
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
* Implementation of [ApiConfigsManager] in MOCK environment
|
||||
|
|
@ -17,13 +18,16 @@ import kotlinx.coroutines.flow.update
|
|||
*/
|
||||
internal class MockApiConfigsManager(
|
||||
private val apiConfigs: ApiConfigs,
|
||||
) : MutableApiConfigsManager {
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : MutableApiConfigsManager() {
|
||||
|
||||
override val configs: StateFlow<Map<ApiConfig, ApiEnvironment>>
|
||||
field = MutableStateFlow(value = getInitialConfigs())
|
||||
|
||||
override val isInitialized: StateFlow<Boolean> = MutableStateFlow(value = true)
|
||||
|
||||
private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default)
|
||||
|
||||
override fun initialize() = Unit
|
||||
|
||||
override fun getEnvironmentConfig(id: ApiConfig.ID): ApiEnvironmentConfig {
|
||||
|
|
@ -55,6 +59,20 @@ internal class MockApiConfigsManager(
|
|||
}
|
||||
}
|
||||
|
||||
override fun addListener(listener: ApiConfigEnvChangeListener) {
|
||||
super.addListener(listener)
|
||||
|
||||
configs
|
||||
.map { it.entries.firstOrNull { it.key.id == listener.id } }
|
||||
.filterNotNull()
|
||||
.onEach { (apiConfig, currentEnvironment) ->
|
||||
listener.onChange(
|
||||
environmentConfig = apiConfig.environmentConfigs.first { it.environment == currentEnvironment },
|
||||
)
|
||||
}
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
|
||||
private fun getInitialConfigs(): Map<ApiConfig, ApiEnvironment> {
|
||||
return apiConfigs.associateWith { it.defaultEnvironment }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.datasource.api.common.config.managers
|
|||
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironmentConfig
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
|
|
@ -9,14 +10,41 @@ import kotlinx.coroutines.flow.Flow
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface MutableApiConfigsManager : ApiConfigsManager {
|
||||
abstract class MutableApiConfigsManager : ApiConfigsManager {
|
||||
|
||||
/** Api configs with current [ApiEnvironment] */
|
||||
val configs: Flow<Map<ApiConfig, ApiEnvironment>>
|
||||
abstract val configs: Flow<Map<ApiConfig, ApiEnvironment>>
|
||||
|
||||
/**
|
||||
* A set of listeners registered to observe changes in API environment configurations.
|
||||
* These listeners are notified whenever an environment change occurs.
|
||||
*/
|
||||
protected val registerListeners: Set<ApiConfigEnvChangeListener>
|
||||
field = mutableSetOf<ApiConfigEnvChangeListener>()
|
||||
|
||||
/** Change api environment [environment] by [id] */
|
||||
suspend fun changeEnvironment(id: String, environment: ApiEnvironment)
|
||||
abstract suspend fun changeEnvironment(id: String, environment: ApiEnvironment)
|
||||
|
||||
/** Change api environment [environment] for all configs */
|
||||
suspend fun changeEnvironment(environment: ApiEnvironment)
|
||||
abstract suspend fun changeEnvironment(environment: ApiEnvironment)
|
||||
|
||||
/** Adds a [listener] to observe changes in API environment configurations */
|
||||
open fun addListener(listener: ApiConfigEnvChangeListener) {
|
||||
registerListeners += listener
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for observing changes in API environment configurations
|
||||
*
|
||||
* @property id the identifier of the API configuration this listener is associated with
|
||||
*/
|
||||
abstract class ApiConfigEnvChangeListener(val id: ApiConfig.ID) {
|
||||
|
||||
/**
|
||||
* Called when the environment configuration changes
|
||||
*
|
||||
* @param environmentConfig the updated [ApiEnvironmentConfig] for the associated API configuration
|
||||
*/
|
||||
abstract fun onChange(environmentConfig: ApiEnvironmentConfig)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import retrofit2.http.Query
|
|||
interface TangemTechMarketsApi {
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@GET("coins/list")
|
||||
@GET("v1/coins/list")
|
||||
suspend fun getCoinsList(
|
||||
@Query("currency") currency: String,
|
||||
@Query("interval") interval: String,
|
||||
|
|
@ -20,24 +20,24 @@ interface TangemTechMarketsApi {
|
|||
@Query("timestamp") timestamp: Long?,
|
||||
): ApiResponse<TokenMarketListResponse>
|
||||
|
||||
@GET("coins/{coin_id}")
|
||||
@GET("v1/coins/{coin_id}")
|
||||
suspend fun getCoinMarketData(
|
||||
@Path("coin_id") coinId: String,
|
||||
@Query("currency") currency: String,
|
||||
@Query("language") language: String,
|
||||
): ApiResponse<TokenMarketInfoResponse>
|
||||
|
||||
@GET("coins/{coin_id}/history")
|
||||
@GET("v1/coins/{coin_id}/history")
|
||||
suspend fun getCoinChart(
|
||||
@Path("coin_id") coinId: String,
|
||||
@Query("currency") currency: String,
|
||||
@Query("interval") interval: String,
|
||||
): ApiResponse<TokenMarketChartResponse>
|
||||
|
||||
@GET("coins/{coin_id}/exchanges")
|
||||
@GET("v1/coins/{coin_id}/exchanges")
|
||||
suspend fun getCoinExchanges(@Path("coin_id") coinId: String): ApiResponse<TokenMarketExchangesResponse>
|
||||
|
||||
@GET("coins/history_preview")
|
||||
@GET("v1/coins/history_preview")
|
||||
suspend fun getCoinsListCharts(
|
||||
@Query("coin_ids") coinIds: String,
|
||||
@Query("currency") currency: String,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import java.util.concurrent.TimeUnit
|
|||
@Suppress("TooManyFunctions")
|
||||
interface TangemTechApi {
|
||||
|
||||
@GET("coins")
|
||||
@GET("v1/coins")
|
||||
suspend fun getCoins(
|
||||
@Header("Cache-Control") cacheControl: String = "max-age=600",
|
||||
@Query("contractAddress") contractAddress: String? = null,
|
||||
|
|
@ -30,150 +30,150 @@ interface TangemTechApi {
|
|||
@Query("limit") limit: Int? = null,
|
||||
): ApiResponse<CoinsResponse>
|
||||
|
||||
@GET("rates")
|
||||
@GET("v1/rates")
|
||||
suspend fun getRates(@Query("currencyId") currencyId: String, @Query("coinIds") coinIds: String): RatesResponse
|
||||
|
||||
@GET("currencies")
|
||||
@GET("v1/currencies")
|
||||
suspend fun getCurrencyList(
|
||||
@Header("Cache-Control") cacheControl: String = "max-age=600",
|
||||
): ApiResponse<CurrenciesResponse>
|
||||
|
||||
@GET("geo")
|
||||
@GET("v1/geo")
|
||||
suspend fun getUserCountryCode(): GeoResponse
|
||||
|
||||
@GET("user-tokens/{user-id}")
|
||||
@GET("v1/user-tokens/{user-id}")
|
||||
suspend fun getUserTokens(@Path(value = "user-id") userId: String): ApiResponse<UserTokensResponse>
|
||||
|
||||
@PUT("user-tokens/{user-id}")
|
||||
@PUT("v1/user-tokens/{user-id}")
|
||||
suspend fun saveUserTokens(
|
||||
@Path(value = "user-id") userId: String,
|
||||
@Body userTokens: UserTokensResponse,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@POST("user-tokens")
|
||||
@POST("v1/user-tokens")
|
||||
suspend fun markUserWallerWasCreated(@Body body: MarkUserWalletWasCreatedBody): ApiResponse<Unit>
|
||||
|
||||
/** Returns referral status by [walletId] */
|
||||
@GET("referral/{walletId}")
|
||||
@GET("v1/referral/{walletId}")
|
||||
suspend fun getReferralStatus(@Path("walletId") walletId: String): ApiResponse<ReferralResponse>
|
||||
|
||||
/** Make user referral, requires [StartReferralBody] */
|
||||
@POST("referral")
|
||||
@POST("v1/referral")
|
||||
suspend fun startReferral(@Body startReferralBody: StartReferralBody): ApiResponse<ReferralResponse>
|
||||
|
||||
@GET("quotes")
|
||||
@GET("v1/quotes")
|
||||
suspend fun getQuotes(
|
||||
@Query("currencyId") currencyId: String,
|
||||
@Query("coinIds") coinIds: String,
|
||||
@Query("fields") fields: String,
|
||||
): ApiResponse<QuotesResponse>
|
||||
|
||||
@GET("promotion")
|
||||
@GET("v1/promotion")
|
||||
suspend fun getPromotionInfo(
|
||||
@Query("programName") name: String,
|
||||
@Header("Cache-Control") cacheControl: String = "max-age=600",
|
||||
): ApiResponse<PromotionInfoResponse>
|
||||
|
||||
@GET("settings/{wallet_id}")
|
||||
@GET("v1/settings/{wallet_id}")
|
||||
suspend fun getUserTokensSettings(@Path("wallet_id") walletId: String): ApiResponse<UserTokensSettingsResponse>
|
||||
|
||||
@PUT("settings/{wallet_id}")
|
||||
@PUT("v1/settings/{wallet_id}")
|
||||
suspend fun saveUserTokensSettings(
|
||||
@Path("wallet_id") walletId: String,
|
||||
@Body userTokensSettings: UserTokensSettingsResponse,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@POST("user-network-account")
|
||||
@POST("v1/user-network-account")
|
||||
suspend fun createUserNetworkAccount(
|
||||
@Body body: CreateUserNetworkAccountBody,
|
||||
): ApiResponse<CreateUserNetworkAccountResponse>
|
||||
|
||||
@POST("account")
|
||||
@POST("v1/account")
|
||||
suspend fun createUserTokensAccount(
|
||||
@Body body: CreateUserTokensAccountBody,
|
||||
): ApiResponse<UserTokensAccountResponse>
|
||||
|
||||
@PUT("account/{account_id}")
|
||||
@PUT("v1/account/{account_id}")
|
||||
suspend fun updateUserTokensAccount(
|
||||
@Path("account_id") accountId: Int,
|
||||
@Body body: UpdateUserTokensAccountBody,
|
||||
): ApiResponse<UserTokensAccountResponse>
|
||||
|
||||
@PUT("account/{account_id}/archive")
|
||||
@PUT("v1/account/{account_id}/archive")
|
||||
suspend fun archiveUserTokensAccount(@Path("account_id") accountId: Int): ApiResponse<UserTokensAccountResponse>
|
||||
|
||||
@PUT("account/{account_id}/unarchive")
|
||||
@PUT("v1/account/{account_id}/unarchive")
|
||||
suspend fun restoreUserTokensAccount(@Path("account_id") accountId: Int): ApiResponse<UserTokensAccountResponse>
|
||||
|
||||
@GET("features")
|
||||
@GET("v1/features")
|
||||
suspend fun getFeatures(): ApiResponse<FeaturesResponse>
|
||||
|
||||
@ReadTimeout(duration = 5, unit = TimeUnit.SECONDS)
|
||||
@GET("networks/providers")
|
||||
@GET("v1/networks/providers")
|
||||
suspend fun getBlockchainProviders(): Map<String, List<ProviderModel>>
|
||||
|
||||
@GET("seedphrase-notification/{wallet_id}")
|
||||
@GET("v1/seedphrase-notification/{wallet_id}")
|
||||
suspend fun getSeedPhraseNotificationStatus(
|
||||
@Path("wallet_id") walletId: String,
|
||||
): ApiResponse<SeedPhraseNotificationDTO>
|
||||
|
||||
@PUT("seedphrase-notification/{wallet_id}")
|
||||
@PUT("v1/seedphrase-notification/{wallet_id}")
|
||||
suspend fun updateSeedPhraseNotificationStatus(
|
||||
@Path("wallet_id") walletId: String,
|
||||
@Body body: SeedPhraseNotificationDTO,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@GET("seedphrase-notification/{wallet_id}/confirmed")
|
||||
@GET("v1/seedphrase-notification/{wallet_id}/confirmed")
|
||||
suspend fun getSeedPhraseSecondNotificationStatus(
|
||||
@Path("wallet_id") walletId: String,
|
||||
): ApiResponse<SeedPhraseNotificationDTO>
|
||||
|
||||
@PUT("seedphrase-notification/{wallet_id}/confirmed")
|
||||
@PUT("v1/seedphrase-notification/{wallet_id}/confirmed")
|
||||
suspend fun updateSeedPhraseSecondNotificationStatus(
|
||||
@Path("wallet_id") walletId: String,
|
||||
@Body body: SeedPhraseNotificationDTO,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@GET("hot_crypto")
|
||||
@GET("v1/hot_crypto")
|
||||
suspend fun getHotCrypto(@Query("currency") currencyId: String): ApiResponse<HotCryptoResponse>
|
||||
|
||||
@GET("stories/{story_id}")
|
||||
@GET("v1/stories/{story_id}")
|
||||
suspend fun getStoryById(@Path("story_id") storyId: String): ApiResponse<StoryContentResponse>
|
||||
|
||||
// region push notifications
|
||||
@GET("notification/push_notifications_eligible_networks")
|
||||
@GET("v1/notification/push_notifications_eligible_networks")
|
||||
suspend fun getEligibleNetworksForPushNotifications(): ApiResponse<List<CryptoNetworkResponse>>
|
||||
|
||||
@POST("user-wallets/applications/")
|
||||
@POST("v1/user-wallets/applications/")
|
||||
suspend fun createApplicationId(
|
||||
@Body
|
||||
body: NotificationApplicationCreateBody,
|
||||
): ApiResponse<NotificationApplicationIdResponse>
|
||||
|
||||
@PATCH("user-wallets/applications/{application_id}")
|
||||
@PATCH("v1/user-wallets/applications/{application_id}")
|
||||
suspend fun updatePushTokenForApplicationId(
|
||||
@Path("application_id") applicationId: String,
|
||||
@Body body: NotificationApplicationCreateBody,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@PATCH("user-wallets/wallets/{wallet_id}/notify")
|
||||
@PATCH("v1/user-wallets/wallets/{wallet_id}/notify")
|
||||
suspend fun setNotificationsEnabled(@Path("wallet_id") walletId: String, @Body body: WalletBody): ApiResponse<Unit>
|
||||
// endregion
|
||||
|
||||
// region wallets
|
||||
@PATCH("user-wallets/wallets/{wallet_id}")
|
||||
@PATCH("v1/user-wallets/wallets/{wallet_id}")
|
||||
suspend fun updateWallet(@Path("wallet_id") walletId: String, @Body body: WalletBody): ApiResponse<Unit>
|
||||
|
||||
@POST("user-wallets/wallets/create-and-connect-by-appuid/{application_id}")
|
||||
@POST("v1/user-wallets/wallets/create-and-connect-by-appuid/{application_id}")
|
||||
suspend fun associateApplicationIdWithWallets(
|
||||
@Path("application_id") applicationId: String,
|
||||
@Body body: List<WalletIdBody>,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@GET("user-wallets/wallets/{wallet_id}")
|
||||
@GET("v1/user-wallets/wallets/{wallet_id}")
|
||||
suspend fun getWalletById(@Path("wallet_id") walletId: String): ApiResponse<WalletResponse>
|
||||
|
||||
@GET("user-wallets/wallets/by-app/{app_id}")
|
||||
@GET("v1/user-wallets/wallets/by-app/{app_id}")
|
||||
suspend fun getWallets(@Path("app_id") appId: String): ApiResponse<List<WalletResponse>>
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ internal object NetworkModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
): ApiConfigsManager {
|
||||
return when {
|
||||
BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE -> MockApiConfigsManager(apiConfigs)
|
||||
BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE -> MockApiConfigsManager(apiConfigs, dispatchers)
|
||||
BuildConfig.TESTER_MENU_ENABLED -> DevApiConfigsManager(apiConfigs, appPreferencesStore, dispatchers)
|
||||
else -> ProdApiConfigsManager(apiConfigs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
package com.tangem.datasource.api.common.config
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import io.mockk.mockk
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class ApiConfigTest {
|
||||
|
||||
@Test
|
||||
fun `all baseUrls ends with slash`() {
|
||||
// Arrange
|
||||
val allBaseUrls = createApiConfigs().flatMap { it.environmentConfigs.map { it.baseUrl } }
|
||||
|
||||
// Actual
|
||||
val actual = allBaseUrls.all { it.endsWith("/") }
|
||||
|
||||
Timber.e(allBaseUrls.joinToString(separator = "\n"))
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
}
|
||||
|
||||
private fun createApiConfigs(): ApiConfigs {
|
||||
return ApiConfig.ID.entries.mapTo(destination = hashSetOf()) {
|
||||
when (it) {
|
||||
ApiConfig.ID.Express -> {
|
||||
Express(
|
||||
environmentConfigStorage = mockk(),
|
||||
expressAuthProvider = mockk(),
|
||||
appVersionProvider = mockk(),
|
||||
appInfoProvider = mockk(),
|
||||
)
|
||||
}
|
||||
ApiConfig.ID.TangemTech -> {
|
||||
TangemTech(
|
||||
appVersionProvider = mockk(),
|
||||
authProvider = mockk(),
|
||||
appInfoProvider = mockk(),
|
||||
)
|
||||
}
|
||||
ApiConfig.ID.StakeKit -> StakeKit(stakeKitAuthProvider = mockk())
|
||||
ApiConfig.ID.TangemPay -> TangemPay(appVersionProvider = mockk())
|
||||
ApiConfig.ID.BlockAid -> BlockAid(configStorage = mockk())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
id = ApiConfig.ID.TangemTech,
|
||||
expected = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.tangem.org/v1/",
|
||||
baseUrl = "https://api.tangem.org/",
|
||||
headers = mapOf(
|
||||
"card_id" to ProviderSuspend { APP_CARD_ID },
|
||||
"card_public_key" to ProviderSuspend { APP_CARD_PUBLIC_KEY },
|
||||
|
|
|
|||
|
|
@ -70,8 +70,4 @@ internal class DefaultCardSdkConfigRepository(
|
|||
override fun setLinkedTerminal(isLinked: Boolean?) {
|
||||
sdk.config.linkedTerminal = isLinked
|
||||
}
|
||||
|
||||
override fun setTangemApiProdEnvFlag(flag: Boolean) {
|
||||
// TODO: [REDACTED_TASK_KEY] Change API's base URL in CardSDK if API environment is changed
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,4 @@ 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)
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ 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
|
||||
|
|
@ -30,7 +29,6 @@ import javax.inject.Inject
|
|||
@HiltViewModel
|
||||
internal class EnvironmentsTogglesViewModel @Inject constructor(
|
||||
apiConfigsManager: ApiConfigsManager,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Current ui state */
|
||||
|
|
@ -98,24 +96,7 @@ internal class EnvironmentsTogglesViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
val environment = ApiEnvironment.valueOf(name)
|
||||
|
||||
if (id == ApiConfig.ID.TangemTech.name) {
|
||||
handleTangemTechConfig(environment = environment)
|
||||
}
|
||||
|
||||
mutableApiConfigsManager.changeEnvironment(id = id, environment = environment)
|
||||
}
|
||||
}
|
||||
|
||||
/** Special logic for [ApiConfig.ID.TangemTech] */
|
||||
private fun handleTangemTechConfig(environment: ApiEnvironment) {
|
||||
cardSdkConfigRepository.setTangemApiProdEnvFlag(
|
||||
flag = when (environment) {
|
||||
ApiEnvironment.PROD -> true
|
||||
ApiEnvironment.DEV,
|
||||
ApiEnvironment.STAGE,
|
||||
ApiEnvironment.MOCK,
|
||||
-> false
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue