Updated on 2026-08-14

This commit is contained in:
Tangem 2023-01-10 14:16:28 +04:00
parent 1675b44cd3
commit da0318964e
25 changed files with 186 additions and 212 deletions

View file

@ -2,8 +2,8 @@ package com.tangem.tap.domain.tokens
import com.squareup.moshi.JsonClass
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.datasource.api.tangemTech.CoinsResponse
@JsonClass(generateAdapter = true)
data class CurrencyFromJson(
@ -26,7 +26,6 @@ data class CurrenciesFromJson(
val coins: List<CurrencyFromJson>
)
fun List<ContractFromJson>.toContracts(): List<Contract> {
return mapNotNull { Contract.fromJsonObject(it) }
}

View file

@ -4,15 +4,17 @@ import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.services.Result
import com.tangem.domain.common.extensions.getListOfCoins
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.datasource.api.tangemTech.TangemTechService
import com.tangem.datasource.api.common.MoshiConverter
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.tap.common.AssetReader
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
class LoadAvailableCoinsService(
private val networkService: TangemTechService,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
private val assetReader: AssetReader,
) {
private val moshi: Moshi by lazy { MoshiConverter.defaultMoshi() }
@ -55,16 +57,23 @@ class LoadAvailableCoinsService(
private suspend fun loadCoins(
supportedBlockchains: List<Blockchain>,
offset: Int,
searchInput: String? = null
searchInput: String? = null,
): Result<CoinsResponse> {
val networkIds = supportedBlockchains.toSet().map { it.toNetworkId() }
return networkService.getListOfCoins(
networkIds = networkIds,
active = true,
offset = offset,
limit = LOAD_PER_PAGE,
searchText = searchInput,
)
return withContext(dispatchers.io) {
runCatching {
tangemTechApi.getCoins(
networkIds = supportedBlockchains.toSet().map(Blockchain::toNetworkId).joinToString(","),
active = true,
searchText = searchInput,
offset = offset,
limit = LOAD_PER_PAGE,
)
}
.onSuccess { return@withContext Result.Success(it) }
.onFailure { return@withContext Result.Failure(it) }
throw IllegalStateException("Unreachable code because runCatching must return result")
}
}
fun getTestnetCoins(): List<Currency> {
@ -88,7 +97,6 @@ class LoadAvailableCoinsService(
}
}
data class LoadedCoins(
val currencies: List<Currency>,
val moreAvailable: Boolean,

View file

@ -4,21 +4,21 @@ import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Types
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.common.services.Result
import com.tangem.domain.common.extensions.getTokens
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.datasource.api.tangemTech.TangemTechService
import com.tangem.datasource.api.common.MoshiConverter
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.tap.common.FileReader
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.domain.tokens.models.TokenDao
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
@Deprecated("Use this only for migration")
class OldUserTokensRepository(
private val fileReader: FileReader,
private val tangemNetworkService: TangemTechService,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
) {
private val moshi = MoshiConverter.defaultMoshi()
private val blockchainsAdapter: JsonAdapter<List<Blockchain>> = moshi.adapter(
@ -104,20 +104,27 @@ class OldUserTokensRepository(
return blockchainNetworks
}
private suspend fun getTokensIds(tokens: List<TokenDao>): Map<String, String> = coroutineScope {
private suspend fun getTokensIds(tokens: List<TokenDao>): Map<String, String> = withContext(dispatchers.io) {
tokens.map {
async {
tangemNetworkService.getTokens(
tangemTechApi.getCoins(
contractAddress = it.contractAddress,
networkId = it.blockchainDao.toBlockchain().toNetworkId(),
networkIds = it.blockchainDao.toBlockchain().toNetworkId(),
active = true,
)
}
}.map { it.await() }
.map { (it as? Result.Success)?.data?.coins?.firstOrNull()?.id }
}
.map {
runCatching { it.await() }
.onSuccess { return@map it.coins.firstOrNull()?.id }
.onFailure { return@map null }
throw IllegalStateException("Unreachable code because runCatching must return result")
}
.mapIndexedNotNull { index, id ->
if (id == null) null else tokens[index].contractAddress to id
}.toMap()
}
.toMap()
}
companion object {

View file

@ -16,7 +16,6 @@ import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.models.toBlockchainNetworks
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.tap.network.NetworkConnectivity
import com.tangem.tap.store
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
@ -120,9 +119,12 @@ class UserTokensRepository(
// TODO("After adding DI") get dependencies by DI
fun init(context: Context, tangemTechService: TangemTechService): UserTokensRepository {
val fileReader = AndroidFileReader(context)
val dispatchers = AppCoroutineDispatcherProvider()
val oldUserTokensRepository = OldUserTokensRepository(
fileReader = fileReader,
tangemNetworkService = store.state.domainNetworks.tangemTechService,
tangemTechApi = tangemTechService.api,
dispatchers = dispatchers,
)
val storageService = UserTokensStorageService(
oldUserTokensRepository = oldUserTokensRepository,
@ -132,7 +134,7 @@ class UserTokensRepository(
return UserTokensRepository(
storageService = storageService,
tangemTechApi = tangemTechService.api,
dispatchers = AppCoroutineDispatcherProvider(),
dispatchers = dispatchers,
)
}
}

View file

@ -1,14 +1,14 @@
package com.tangem.tap.domain.tokens.converters
import com.tangem.datasource.api.tangemTech.models.TokenBody
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.utils.converter.Converter
/** Converter from domain model [Currency] to data model [TokenBody] */
object CurrencyConverter : Converter<Currency, TokenBody> {
/** Converter from domain model [Currency] to data model [UserTokensResponse.Token] */
object CurrencyConverter : Converter<Currency, UserTokensResponse.Token> {
override fun convert(value: Currency) = TokenBody(
override fun convert(value: Currency) = UserTokensResponse.Token(
id = value.coinId,
networkId = value.blockchain.toNetworkId(),
derivationPath = value.derivationPath,

View file

@ -40,6 +40,7 @@ import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import com.tangem.tap.userWalletsListManager
import com.tangem.tap.walletCurrenciesManager
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.rekotlin.Middleware
@ -83,8 +84,9 @@ class TokensMiddleware {
.filter { !it.isTestnet() }
val loadCoinsService = LoadAvailableCoinsService(
store.state.domainNetworks.tangemTechService,
assetReader,
tangemTechApi = store.state.domainNetworks.tangemTechService.api,
dispatchers = AppCoroutineDispatcherProvider(),
assetReader = assetReader,
)
scope.launch {

View file

@ -1,7 +1,7 @@
package com.tangem.tap.features.wallet.models
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.datasource.api.tangemTech.models.TokenBody
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.features.addCustomToken.CustomCurrency
@ -98,7 +98,7 @@ sealed interface Currency {
)
}
fun fromTokenResponse(tokenBody: TokenBody): Currency? {
fun fromTokenResponse(tokenBody: UserTokensResponse.Token): Currency? {
val blockchain = com.tangem.blockchain.common.Blockchain.fromNetworkId(tokenBody.networkId)
?: return null
return when {

View file

@ -1,6 +1,6 @@
package com.tangem.tap.features.wallet.redux.middlewares
import com.tangem.datasource.api.tangemTech.models.Currency
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.MainScreen
@ -38,7 +38,7 @@ class AppCurrencyMiddleware(
store.dispatchDialogShow(
WalletDialog.CurrencySelectionDialog(
currenciesList = storedFiatCurrencies.mapToUiModel(),
currentAppCurrency = appCurrencyProvider.invoke()
currentAppCurrency = appCurrencyProvider.invoke(),
)
)
}
@ -52,7 +52,7 @@ class AppCurrencyMiddleware(
store.dispatchDialogShow(
WalletDialog.CurrencySelectionDialog(
currenciesList = currenciesList.mapToUiModel(),
currentAppCurrency = appCurrencyProvider.invoke()
currentAppCurrency = appCurrencyProvider.invoke(),
)
)
}
@ -77,7 +77,7 @@ class AppCurrencyMiddleware(
}
}
private fun List<Currency>.mapToUiModel(): List<FiatCurrency> {
private fun List<CurrenciesResponse.Currency>.mapToUiModel(): List<FiatCurrency> {
return this.map {
FiatCurrency(
code = it.code,

View file

@ -3,7 +3,7 @@ package com.tangem.tap.persistence
import android.content.SharedPreferences
import androidx.core.content.edit
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.datasource.api.tangemTech.models.Currency
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.tap.common.entities.FiatCurrency
/**
@ -32,14 +32,14 @@ class FiatCurrenciesPrefStorage(
preferences.edit { putString(APP_CURRENCY_KEY, json) }
}
fun save(currencies: List<Currency>) {
fun save(currencies: List<CurrenciesResponse.Currency>) {
val json: String = converter.toJson(currencies)
return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply()
}
fun restore(): List<Currency> {
fun restore(): List<CurrenciesResponse.Currency> {
val json = preferences.getString(FIAT_CURRENCIES_KEY, "")
val type = converter.typedList(Currency::class.java)
val type = converter.typedList(CurrenciesResponse.Currency::class.java)
if (json.isNullOrBlank()) return emptyList()
return converter.fromJson(json, type) ?: emptyList()