Updated on 2026-08-14
This commit is contained in:
parent
acf110dbcc
commit
6910f74fd9
242 changed files with 866 additions and 732 deletions
|
|
@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
interface ApiConfigsManager {
|
||||
|
||||
/** Flag that determines whether the manager is initialized */
|
||||
val isInitialized: StateFlow<Boolean>
|
||||
val initializedState: StateFlow<Boolean>
|
||||
|
||||
/** Initialize resources */
|
||||
fun initialize()
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ internal class DevApiConfigsManager(
|
|||
override val configs: StateFlow<Map<ApiConfig, ApiEnvironment>>
|
||||
field = MutableStateFlow(value = getInitialConfigs())
|
||||
|
||||
override val isInitialized: StateFlow<Boolean>
|
||||
override val initializedState: StateFlow<Boolean>
|
||||
field = MutableStateFlow(value = false)
|
||||
|
||||
override fun initialize() {
|
||||
isInitialized.value = false
|
||||
initializedState.value = false
|
||||
|
||||
appPreferencesStore.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
.distinctUntilChanged()
|
||||
|
|
@ -45,8 +45,8 @@ internal class DevApiConfigsManager(
|
|||
savedEnvironments[config.id.name] ?: currentEnvironment
|
||||
}
|
||||
|
||||
if (!isInitialized.value) {
|
||||
isInitialized.value = true
|
||||
if (!initializedState.value) {
|
||||
initializedState.value = true
|
||||
}
|
||||
|
||||
notifyListeners(apiConfigs = apiConfigs, savedEnvironments = savedEnvironments)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ internal class MockApiConfigsManager(
|
|||
override val configs: StateFlow<Map<ApiConfig, ApiEnvironment>>
|
||||
field = MutableStateFlow(value = getInitialConfigs())
|
||||
|
||||
override val isInitialized: StateFlow<Boolean> = MutableStateFlow(value = true)
|
||||
override val initializedState: StateFlow<Boolean> = MutableStateFlow(value = true)
|
||||
|
||||
private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal class ProdApiConfigsManager(
|
|||
private val apiConfigs: ApiConfigs,
|
||||
) : ApiConfigsManager {
|
||||
|
||||
override val isInitialized: StateFlow<Boolean> = MutableStateFlow(value = true)
|
||||
override val initializedState: StateFlow<Boolean> = MutableStateFlow(value = true)
|
||||
|
||||
override fun initialize() = Unit
|
||||
|
||||
|
|
|
|||
|
|
@ -72,14 +72,14 @@ sealed class ApiResponseError : Exception() {
|
|||
|
||||
/** Represents a network error, typically when there's no connectivity. */
|
||||
@Suppress("UnusedPrivateMember")
|
||||
data object NetworkException : ApiResponseError() {
|
||||
private fun readResolve(): Any = NetworkException
|
||||
class NetworkException : ApiResponseError() {
|
||||
private fun readResolve(): Any = NetworkException()
|
||||
}
|
||||
|
||||
/** Represents a timeout error, typically when the server takes too long to respond. */
|
||||
@Suppress("UnusedPrivateMember")
|
||||
data object TimeoutException : ApiResponseError() {
|
||||
private fun readResolve(): Any = TimeoutException
|
||||
class TimeoutException : ApiResponseError() {
|
||||
private fun readResolve(): Any = TimeoutException()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,5 +87,5 @@ sealed class ApiResponseError : Exception() {
|
|||
*
|
||||
* @property cause The exception that caused this error.
|
||||
*/
|
||||
data class UnknownException(override val cause: Throwable) : ApiResponseError()
|
||||
class UnknownException(override val cause: Throwable) : ApiResponseError()
|
||||
}
|
||||
|
|
@ -58,10 +58,10 @@ internal fun Throwable.toApiError(): ApiResponseError = when (this) {
|
|||
is ConnectException,
|
||||
is UnknownHostException,
|
||||
is SSLHandshakeException,
|
||||
-> ApiResponseError.NetworkException
|
||||
-> ApiResponseError.NetworkException()
|
||||
is TimeoutException,
|
||||
is TimeoutCancellationException,
|
||||
is SocketTimeoutException,
|
||||
-> ApiResponseError.TimeoutException
|
||||
-> ApiResponseError.TimeoutException()
|
||||
else -> ApiResponseError.UnknownException(cause = this)
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class Asset(
|
||||
@Json(name = "contractAddress")
|
||||
val contractAddress: String,
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ data class TokenMarketInfoResponse(
|
|||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class Network(
|
||||
@Json(name = "network_id")
|
||||
val networkId: String,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class OnrampCountryDTO(
|
||||
@Json(name = "name")
|
||||
val name: String,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ data class TangemPayTxHistoryResponse(
|
|||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class Spend(
|
||||
@Json(name = "amount") val amount: BigDecimal,
|
||||
@Json(name = "currency") val currency: String,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ data class ActionRequestBody(
|
|||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class ActionRequestBodyArgs(
|
||||
@Json(name = "amount")
|
||||
val amount: String,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.squareup.moshi.JsonClass
|
|||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class AddressArgumentDTO(
|
||||
@Json(name = "required")
|
||||
val required: Boolean,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("BooleanPropertyNaming")
|
||||
|
||||
package com.tangem.datasource.api.stakekit.models.response.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("BooleanPropertyNaming")
|
||||
|
||||
package com.tangem.datasource.api.stakekit.models.response.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("BooleanPropertyNaming")
|
||||
|
||||
package com.tangem.datasource.api.tangemTech.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
|
|
@ -12,12 +14,13 @@ data class CoinsResponse(
|
|||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class Coin(
|
||||
@Json(name = "id") val id: String,
|
||||
@Json(name = "name") val name: String,
|
||||
@Json(name = "symbol") val symbol: String,
|
||||
@Json(name = "active") val active: Boolean,
|
||||
@Json(name = "networks") val networks: List<Network> = listOf(),
|
||||
@Json(name = "networks") val networks: List<Network> = emptyList(),
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class CreateUserNetworkAccountResponse(
|
||||
@Json(name = "status") val status: Boolean,
|
||||
@Json(name = "data") val data: AccountCreated,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.squareup.moshi.JsonClass
|
|||
import com.tangem.common.extensions.calculateHashCode
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class UserTokensResponse(
|
||||
@Json(name = "version") val version: Int = 0,
|
||||
@Json(name = "group") val group: GroupType,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class WalletBody(
|
||||
@Json(name = "notifyStatus") val notifyStatus: Boolean? = null,
|
||||
@Json(name = "name") val name: String? = null,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class WalletResponse(
|
||||
@Json(name = "notifyStatus") val notifyStatus: Boolean,
|
||||
@Json(name = "id") val id: String,
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ class AssetLoader @Inject constructor(
|
|||
if (parsedConfig == null) Timber.e(IllegalStateException("Parsed config [$fileName] is null"))
|
||||
parsedConfig.orEmpty()
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Failed to load config [$fileName] from assets")
|
||||
onFailure = { throwable ->
|
||||
Timber.e(throwable, "Failed to load config [$fileName] from assets")
|
||||
emptyList()
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@ internal class RetrofitApiBuilder @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UseEmptyCounterpart")
|
||||
private companion object {
|
||||
|
||||
val excludedApiForLogging: Set<ApiConfig.ID> = setOf(
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ internal class DefaultExpressServiceLoader @Inject constructor(
|
|||
return flow { getInitializationStatusInternal(userWalletId).collect { emit(it) } }
|
||||
}
|
||||
|
||||
@Suppress("SuspendFunWithFlowReturnType")
|
||||
private suspend fun getInitializationStatusInternal(userWalletId: UserWalletId): InitializationStatusFlow {
|
||||
val initializationStatus = initializationStatuses.value.get(key = userWalletId)
|
||||
if (initializationStatus != null) return initializationStatus
|
||||
|
|
@ -79,8 +80,8 @@ internal class DefaultExpressServiceLoader @Inject constructor(
|
|||
val cached = expressAssetsStore.getSyncOrNull(userWalletId)
|
||||
val default: InitializationStatusFlow = MutableStateFlow(value = cached?.lceContent() ?: lceLoading())
|
||||
|
||||
initializationStatuses.update {
|
||||
it.toMutableMap().apply {
|
||||
initializationStatuses.update { statuses ->
|
||||
statuses.toMutableMap().apply {
|
||||
put(key = userWalletId, value = default)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@ object NFTSdkAssetConverter : TwoWayConverter<Pair<Network, SdkNFTAsset>, NFTAss
|
|||
amount = asset.amount,
|
||||
decimals = asset.decimals,
|
||||
salePrice = salePrice,
|
||||
rarity = asset.rarity?.let {
|
||||
rarity = asset.rarity?.let { rarity ->
|
||||
NFTAsset.Rarity(
|
||||
rank = it.rank,
|
||||
label = it.label,
|
||||
rank = rarity.rank,
|
||||
label = rarity.label,
|
||||
)
|
||||
},
|
||||
media = asset.media?.let {
|
||||
|
|
@ -65,22 +65,22 @@ object NFTSdkAssetConverter : TwoWayConverter<Pair<Network, SdkNFTAsset>, NFTAss
|
|||
amount = value.amount,
|
||||
decimals = value.decimals,
|
||||
salePrice = salePrice,
|
||||
rarity = value.rarity?.let {
|
||||
rarity = value.rarity?.let { rarity ->
|
||||
SdkNFTAsset.Rarity(
|
||||
rank = it.rank,
|
||||
label = it.label,
|
||||
rank = rarity.rank,
|
||||
label = rarity.label,
|
||||
)
|
||||
},
|
||||
media = value.media?.let {
|
||||
media = value.media?.let { media ->
|
||||
SdkNFTAsset.Media(
|
||||
animationUrl = it.animationUrl,
|
||||
imageUrl = it.imageUrl,
|
||||
animationUrl = media.animationUrl,
|
||||
imageUrl = media.imageUrl,
|
||||
)
|
||||
},
|
||||
traits = value.traits.map {
|
||||
traits = value.traits.map { trait ->
|
||||
SdkNFTAsset.Trait(
|
||||
name = it.name,
|
||||
value = it.value,
|
||||
name = trait.name,
|
||||
value = trait.value,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ inline fun <reified T> AppPreferencesStore.getObject(key: Preferences.Key<String
|
|||
return flow {
|
||||
val adapter = moshi.adapter(T::class.java)
|
||||
emitAll(
|
||||
data.map {
|
||||
data.map { prefs ->
|
||||
try {
|
||||
it[key]?.let(adapter::fromJson) ?: default
|
||||
prefs[key]?.let(adapter::fromJson) ?: default
|
||||
} catch (e: JsonDataException) {
|
||||
default
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ internal class DefaultSwapBestRateAnimationStore(
|
|||
* If true, reset flag to false
|
||||
*/
|
||||
override suspend fun getSyncOrNull(): Boolean {
|
||||
val value = dataStore.getSyncOrNull() ?: true
|
||||
if (value) {
|
||||
val shouldShowBestRateAnimation = dataStore.getSyncOrNull() ?: true
|
||||
if (shouldShowBestRateAnimation) {
|
||||
dataStore.store(false)
|
||||
}
|
||||
return value
|
||||
return shouldShowBestRateAnimation
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ internal class DefaultTokenReceiveWarningActionStore(
|
|||
) : TokenReceiveWarningActionStore {
|
||||
|
||||
override suspend fun getSync(): Set<String> {
|
||||
return persistenceStore.data.firstOrNull() ?: emptySet()
|
||||
return persistenceStore.data.firstOrNull().orEmpty()
|
||||
}
|
||||
|
||||
override suspend fun store(symbol: String) {
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ internal object PendingActionConverter : Converter<BalanceDTO.PendingAction, Pen
|
|||
maximum = it.maximum,
|
||||
)
|
||||
},
|
||||
duration = this?.duration?.let {
|
||||
duration = this?.duration?.let { duration ->
|
||||
PendingAction.PendingActionArgs.Duration(
|
||||
required = it.required,
|
||||
minimum = it.minimum,
|
||||
maximum = it.maximum,
|
||||
required = duration.required,
|
||||
minimum = duration.minimum,
|
||||
maximum = duration.maximum,
|
||||
)
|
||||
},
|
||||
validatorAddress = this?.validatorAddress?.required,
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ internal fun OkHttpClient.Builder.addHeaders(
|
|||
Interceptor { chain ->
|
||||
val request = chain.request().newBuilder().apply {
|
||||
runBlocking {
|
||||
requestHeaders.forEach {
|
||||
val value = it.value.invoke()
|
||||
if (value.isNotBlank()) addHeader(name = it.key, value = value)
|
||||
requestHeaders.forEach { header ->
|
||||
val value = header.value.invoke()
|
||||
if (value.isNotBlank()) addHeader(name = header.key, value = value)
|
||||
}
|
||||
}
|
||||
}.build()
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ class NetworkLogsSaveInterceptor(
|
|||
|
||||
private fun logResponseMessage(response: Response, startNs: Long) {
|
||||
val responseHeaders = response.headers
|
||||
val responseBody = response.body!!
|
||||
val responseBody = requireNotNull(response.body)
|
||||
val contentLength = responseBody.contentLength()
|
||||
|
||||
val message = if (!response.promisesBody()) {
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ sealed class RequestHeader(vararg pairs: Pair<String, ProviderSuspend<String>>)
|
|||
fun String.checkHeaderValueOrEmpty(): String {
|
||||
for (i in this.indices) {
|
||||
val c = this[i]
|
||||
val charCondition = c == '\t' || c in '\u0020'..'\u007e'
|
||||
if (!charCondition) {
|
||||
val isChar = c == '\t' || c in '\u0020'..'\u007e'
|
||||
if (!isChar) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue