Updated on 2026-08-14
This commit is contained in:
parent
5f95aadd6c
commit
700731a408
11 changed files with 183 additions and 10 deletions
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.tangem.datasource.api.common.config
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api environment
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
enum class ApiEnvironment {
|
||||||
|
DEV, STAGE, PROD
|
||||||
|
}
|
||||||
|
|
@ -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}]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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}]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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 */
|
/** 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 type = Types.newParameterizedType(Map::class.java, String::class.java, V::class.java)
|
||||||
val adapter = moshi.adapter<Map<String, V>>(type)
|
val adapter = moshi.adapter<Map<String, V>>(type)
|
||||||
|
|
||||||
|
|
@ -135,6 +135,14 @@ suspend inline fun <reified V> AppPreferencesStore.getObjectMap(key: Preferences
|
||||||
.orEmpty()
|
.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 */
|
/** 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> {
|
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))
|
val adapter = moshi.adapter<Set<T>>(Types.newParameterizedType(Set::class.java, T::class.java))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.tangem.data.analytics
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||||
import com.tangem.datasource.local.preferences.utils.getObjectListSync
|
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.model.WalletBalanceState
|
||||||
import com.tangem.domain.analytics.repository.AnalyticsRepository
|
import com.tangem.domain.analytics.repository.AnalyticsRepository
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
@ -29,7 +29,7 @@ internal class DefaultAnalyticsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getWalletBalanceState(userWalletId: UserWalletId): WalletBalanceState? {
|
override suspend fun getWalletBalanceState(userWalletId: UserWalletId): WalletBalanceState? {
|
||||||
val walletsBalanceState = appPreferencesStore.getObjectMap<WalletBalanceState>(
|
val walletsBalanceState = appPreferencesStore.getObjectMapSync<WalletBalanceState>(
|
||||||
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
|
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ internal class DefaultAnalyticsRepository(
|
||||||
val walletsBalanceState = it.getObjectMap<WalletBalanceState>(
|
val walletsBalanceState = it.getObjectMap<WalletBalanceState>(
|
||||||
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
|
key = PreferencesKeys.WALLETS_BALANCES_STATES_KEY,
|
||||||
)
|
)
|
||||||
val updatedWalletsBalanceState = walletsBalanceState.orEmpty()
|
val updatedWalletsBalanceState = walletsBalanceState
|
||||||
.plus(pair = userWalletId.stringValue to balanceState)
|
.plus(pair = userWalletId.stringValue to balanceState)
|
||||||
|
|
||||||
it.setObjectMap(PreferencesKeys.WALLETS_BALANCES_STATES_KEY, updatedWalletsBalanceState)
|
it.setObjectMap(PreferencesKeys.WALLETS_BALANCES_STATES_KEY, updatedWalletsBalanceState)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import com.tangem.data.feedback.converters.BlockchainInfoConverter
|
||||||
import com.tangem.data.feedback.converters.CardInfoConverter
|
import com.tangem.data.feedback.converters.CardInfoConverter
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
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.datasource.local.walletmanager.WalletManagersStore
|
||||||
import com.tangem.domain.feedback.models.*
|
import com.tangem.domain.feedback.models.*
|
||||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||||
|
|
@ -99,7 +99,7 @@ internal class DefaultFeedbackRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAppLogs(): List<AppLogModel> {
|
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) }
|
.map { AppLogModel(timestamp = it.key.toLong(), message = it.value) }
|
||||||
.sortedBy(AppLogModel::timestamp)
|
.sortedBy(AppLogModel::timestamp)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_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_CHECKED_RESET_ACCOUNTS_KEY
|
||||||
import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_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.datasource.local.preferences.utils.getObjectSetSync
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
|
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
|
||||||
|
|
@ -97,7 +97,7 @@ internal class DefaultPolkadotAccountHealthCheckRepository(
|
||||||
runCatching {
|
runCatching {
|
||||||
do {
|
do {
|
||||||
// Getting batch of extrinsics to check
|
// 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 lastExtrinsic = lastChecked[address]
|
||||||
val extrinsicListResult = accountCheckerProvider.getExtrinsicList(afterExtrinsicId = lastExtrinsic)
|
val extrinsicListResult = accountCheckerProvider.getExtrinsicList(afterExtrinsicId = lastExtrinsic)
|
||||||
extrinsicListResult.extrinsic
|
extrinsicListResult.extrinsic
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||||
import com.tangem.datasource.local.preferences.utils.getObjectList
|
import com.tangem.datasource.local.preferences.utils.getObjectList
|
||||||
import com.tangem.datasource.local.preferences.utils.getObjectListSync
|
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.models.scan.ScanResponse
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
@ -75,7 +75,7 @@ class DefaultSwapTransactionRepository(
|
||||||
scanResponse: ScanResponse,
|
scanResponse: ScanResponse,
|
||||||
): Flow<List<SavedSwapTransactionListModel>?> {
|
): Flow<List<SavedSwapTransactionListModel>?> {
|
||||||
return withContext(dispatchers.io) {
|
return withContext(dispatchers.io) {
|
||||||
val txStatuses = appPreferencesStore.getObjectMap<ExchangeStatusModel>(
|
val txStatuses = appPreferencesStore.getObjectMapSync<ExchangeStatusModel>(
|
||||||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||||
)
|
)
|
||||||
appPreferencesStore.getObjectList<SavedSwapTransactionListModelInner>(
|
appPreferencesStore.getObjectList<SavedSwapTransactionListModelInner>(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue