Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-08 18:28:24 +03:00
parent 5f95aadd6c
commit 700731a408
11 changed files with 183 additions and 10 deletions

View file

@ -0,0 +1,50 @@
package com.tangem.datasource.api.common.config
/**
* Api config
*
* @property currentEnvironment current api environment
*
* @see <a href="https://www.notion.so/tangem/API-eacb264e7daf420a88b419a8a26f5b26?pvs=4">API configuration</a>
*
[REDACTED_AUTHOR]
*/
sealed class ApiConfig(open val currentEnvironment: ApiEnvironment) {
/** Available environments with base url */
abstract val environments: Map<ApiEnvironment, String>
/** Unique id */
val id: ID = initializeId()
enum class ID {
Express,
TangemTech,
}
/** Copy method for sealed class [ApiConfig] */
fun copySealed(currentEnvironment: ApiEnvironment): ApiConfig {
return when (this) {
is Express -> copy(currentEnvironment = currentEnvironment)
is TangemTech -> copy(currentEnvironment = currentEnvironment)
}
}
private fun initializeId(): ID {
return when (this) {
is Express -> ID.Express
is TangemTech -> ID.TangemTech
}
}
companion object {
internal const val DEBUG_BUILD_TYPE = "debug"
internal const val INTERNAL_BUILD_TYPE = "internal"
internal const val MOCKED_BUILD_TYPE = "mocked"
internal const val EXTERNAL_BUILD_TYPE = "external"
internal const val RELEASE_BUILD_TYPE = "release"
/** All api configs */
fun values() = listOf(Express(), TangemTech())
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.api.common.config
/**
* Api environment
*
[REDACTED_AUTHOR]
*/
enum class ApiEnvironment {
DEV, STAGE, PROD
}

View file

@ -0,0 +1,35 @@
package com.tangem.datasource.api.common.config
import com.tangem.datasource.BuildConfig
/**
* Express [ApiConfig]
*
* @property currentEnvironment current api environment
*/
internal data class Express(
override val currentEnvironment: ApiEnvironment = initializeCurrentEnvironment(),
) : ApiConfig(currentEnvironment) {
override val environments: Map<ApiEnvironment, String> = mapOf(
ApiEnvironment.DEV to "[REDACTED_ENV_URL]",
ApiEnvironment.STAGE to "[REDACTED_ENV_URL]",
ApiEnvironment.PROD to "https://express.tangem.com/v1/",
)
private companion object {
fun initializeCurrentEnvironment(): ApiEnvironment {
return when (BuildConfig.BUILD_TYPE) {
DEBUG_BUILD_TYPE -> ApiEnvironment.DEV
INTERNAL_BUILD_TYPE,
MOCKED_BUILD_TYPE,
-> ApiEnvironment.STAGE
EXTERNAL_BUILD_TYPE,
RELEASE_BUILD_TYPE,
-> ApiEnvironment.PROD
else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]")
}
}
}
}

View file

@ -0,0 +1,34 @@
package com.tangem.datasource.api.common.config
import com.tangem.datasource.BuildConfig
/**
* TangemTech [ApiConfig]
*
* @property currentEnvironment current api environment
*/
internal data class TangemTech(
override val currentEnvironment: ApiEnvironment = initializeCurrentEnvironment(),
) : ApiConfig(currentEnvironment) {
override val environments: Map<ApiEnvironment, String> = mapOf(
ApiEnvironment.DEV to "https://devapi.tangem-tech.com/v1/",
ApiEnvironment.PROD to "https://api.tangem-tech.com/v1/",
)
private companion object {
fun initializeCurrentEnvironment(): ApiEnvironment {
return when (BuildConfig.BUILD_TYPE) {
DEBUG_BUILD_TYPE,
INTERNAL_BUILD_TYPE,
-> ApiEnvironment.DEV
MOCKED_BUILD_TYPE,
EXTERNAL_BUILD_TYPE,
RELEASE_BUILD_TYPE,
-> ApiEnvironment.PROD
else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]")
}
}
}
}

View file

@ -0,0 +1,17 @@
package com.tangem.datasource.api.common.config.managers
import com.tangem.datasource.api.common.config.ApiConfig
/**
* Api configs manager
*
[REDACTED_AUTHOR]
*/
interface ApiConfigsManager {
/** Initialize resources */
suspend fun initialize() {}
/** Get base url of api by [id] */
fun getBaseUrl(id: ApiConfig.ID): String
}

View file

@ -0,0 +1,19 @@
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 kotlinx.coroutines.flow.Flow
/**
* Mutable [ApiConfigsManager] for change information about the current api environment
*
[REDACTED_AUTHOR]
*/
interface MutableApiConfigsManager : ApiConfigsManager {
/** Configs */
val configs: Flow<List<ApiConfig>>
/** Change api environment [environment] by [id] */
suspend fun changeEnvironment(id: String, environment: ApiEnvironment)
}

View file

@ -125,7 +125,7 @@ suspend inline fun <reified V> AppPreferencesStore.storeObjectMap(
}
/** Get map with [String] key and value [V] by string [key], or empty if data is not found */
suspend inline fun <reified V> AppPreferencesStore.getObjectMap(key: Preferences.Key<String>): Map<String, V> {
suspend inline fun <reified V> AppPreferencesStore.getObjectMapSync(key: Preferences.Key<String>): Map<String, V> {
val type = Types.newParameterizedType(Map::class.java, String::class.java, V::class.java)
val adapter = moshi.adapter<Map<String, V>>(type)
@ -135,6 +135,14 @@ suspend inline fun <reified V> AppPreferencesStore.getObjectMap(key: Preferences
.orEmpty()
}
/** Get flow of map with [String] key and value [V] by string [key], or empty if data is not found */
inline fun <reified V> AppPreferencesStore.getObjectMap(key: Preferences.Key<String>): Flow<Map<String, V>> {
val type = Types.newParameterizedType(Map::class.java, String::class.java, V::class.java)
val adapter = moshi.adapter<Map<String, V>>(type)
return data.map { it[key]?.let(adapter::fromJson) ?: emptyMap() }
}
/** Get set of data [T] by string [key], or empty if data is not found */
suspend inline fun <reified T> AppPreferencesStore.getObjectSetSync(key: Preferences.Key<String>): Set<T> {
val adapter = moshi.adapter<Set<T>>(Types.newParameterizedType(Set::class.java, T::class.java))

View file

@ -3,7 +3,7 @@ package com.tangem.data.analytics
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectListSync
import com.tangem.datasource.local.preferences.utils.getObjectMap
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.domain.analytics.model.WalletBalanceState
import com.tangem.domain.analytics.repository.AnalyticsRepository
import com.tangem.domain.wallets.models.UserWalletId
@ -29,7 +29,7 @@ internal class DefaultAnalyticsRepository(
}
override suspend fun getWalletBalanceState(userWalletId: UserWalletId): WalletBalanceState? {
val walletsBalanceState = appPreferencesStore.getObjectMap<WalletBalanceState>(
val walletsBalanceState = appPreferencesStore.getObjectMapSync<WalletBalanceState>(
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
)
@ -41,7 +41,7 @@ internal class DefaultAnalyticsRepository(
val walletsBalanceState = it.getObjectMap<WalletBalanceState>(
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
)
val updatedWalletsBalanceState = walletsBalanceState.orEmpty()
val updatedWalletsBalanceState = walletsBalanceState
.plus(pair = userWalletId.stringValue to balanceState)
it.setObjectMap(PreferencesKeys.WALLETS_BALANCES_STATES_KEY, updatedWalletsBalanceState)

View file

@ -8,7 +8,7 @@ import com.tangem.data.feedback.converters.BlockchainInfoConverter
import com.tangem.data.feedback.converters.CardInfoConverter
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.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.datasource.local.walletmanager.WalletManagersStore
import com.tangem.domain.feedback.models.*
import com.tangem.domain.feedback.repository.FeedbackRepository
@ -99,7 +99,7 @@ internal class DefaultFeedbackRepository(
}
override suspend fun getAppLogs(): List<AppLogModel> {
return appPreferencesStore.getObjectMap<String>(key = PreferencesKeys.APP_LOGS_KEY)
return appPreferencesStore.getObjectMapSync<String>(key = PreferencesKeys.APP_LOGS_KEY)
.map { AppLogModel(timestamp = it.key.toLong(), message = it.value) }
.sortedBy(AppLogModel::timestamp)
}

View file

@ -9,7 +9,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY
import com.tangem.datasource.local.preferences.utils.getObjectMap
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.datasource.local.preferences.utils.getObjectSetSync
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
@ -97,7 +97,7 @@ internal class DefaultPolkadotAccountHealthCheckRepository(
runCatching {
do {
// Getting batch of extrinsics to check
val lastChecked = appPreferencesStore.getObjectMap<Long>(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY)
val lastChecked = appPreferencesStore.getObjectMapSync<Long>(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY)
val lastExtrinsic = lastChecked[address]
val extrinsicListResult = accountCheckerProvider.getExtrinsicList(afterExtrinsicId = lastExtrinsic)
extrinsicListResult.extrinsic

View file

@ -4,7 +4,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectList
import com.tangem.datasource.local.preferences.utils.getObjectListSync
import com.tangem.datasource.local.preferences.utils.getObjectMap
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
@ -75,7 +75,7 @@ class DefaultSwapTransactionRepository(
scanResponse: ScanResponse,
): Flow<List<SavedSwapTransactionListModel>?> {
return withContext(dispatchers.io) {
val txStatuses = appPreferencesStore.getObjectMap<ExchangeStatusModel>(
val txStatuses = appPreferencesStore.getObjectMapSync<ExchangeStatusModel>(
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
)
appPreferencesStore.getObjectList<SavedSwapTransactionListModelInner>(