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()

View file

@ -1,35 +0,0 @@
package com.tangem.datasource.api.tangemTech
import java.math.BigDecimal
/**
[REDACTED_AUTHOR]
*/
interface HttpResponse
sealed interface TangemTechResponse : HttpResponse
data class CoinsResponse(
val imageHost: String?,
val coins: List<Coin>,
val total: Int,
) : TangemTechResponse {
data class Coin(
val id: String,
val name: String,
val symbol: String,
val active: Boolean,
val networks: List<Network> = listOf(),
) : TangemTechResponse {
data class Network(
val networkId: String,
val contractAddress: String? = null,
val decimalCount: BigDecimal? = null,
val exchangeable: Boolean? = false,
) : TangemTechResponse
}
}
//rates.keys = networkId's
data class RatesResponse(val rates: Map<String, Double>) : TangemTechResponse

View file

@ -1,7 +1,9 @@
package com.tangem.datasource.api.tangemTech
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.datasource.api.tangemTech.models.GeoResponse
import com.tangem.datasource.api.tangemTech.models.RatesResponse
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import retrofit2.http.Body
import retrofit2.http.GET
@ -10,12 +12,14 @@ import retrofit2.http.Path
import retrofit2.http.Query
/**
* Interface of Tangem Tech API
*
[REDACTED_AUTHOR]
*/
interface TangemTechApi {
@GET("coins")
suspend fun coins(
suspend fun getCoins(
@Query("contractAddress") contractAddress: String? = null,
@Query("exchangeable") exchangeable: Boolean? = null,
@Query("networkIds") networkIds: String? = null,

View file

@ -1,12 +1,8 @@
package com.tangem.datasource.api.tangemTech
import com.tangem.common.services.Result
import com.tangem.common.services.performRequest
import com.tangem.datasource.api.common.AddHeaderInterceptor
import com.tangem.datasource.api.common.CacheControlHttpInterceptor
import com.tangem.datasource.api.common.createRetrofitInstance
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
/**
[REDACTED_AUTHOR]
@ -21,26 +17,6 @@ class TangemTechService(
var api: TangemTechApi = createApi()
suspend fun coins(
contractAddress: String? = null,
networkIds: String? = null,
active: Boolean? = null,
searchText: String? = null,
offset: Int? = null,
limit: Int? = null,
): Result<CoinsResponse> = withContext(Dispatchers.IO) {
performRequest {
api.coins(
contractAddress = contractAddress,
networkIds = networkIds,
active = active,
searchText = searchText,
offset = offset,
limit = limit,
)
}
}
fun addHeaderInterceptors(interceptors: List<AddHeaderInterceptor>) {
headerInterceptors.removeAll(interceptors)
headerInterceptors.addAll(interceptors)

View file

@ -0,0 +1,27 @@
package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json
import java.math.BigDecimal
data class CoinsResponse(
@Json(name = "imageHost") val imageHost: String?,
@Json(name = "coins") val coins: List<Coin>,
@Json(name = "total") val total: Int,
) {
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(),
) {
data class Network(
@Json(name = "networkId") val networkId: String,
@Json(name = "contractAddress") val contractAddress: String? = null,
@Json(name = "decimalCount") val decimalCount: BigDecimal? = null,
@Json(name = "exchangeable") val exchangeable: Boolean? = false,
)
}
}

View file

@ -3,14 +3,15 @@ package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json
data class CurrenciesResponse(
@Json(name = "currencies") val currencies: List<Currency>
)
@Json(name = "currencies") val currencies: List<Currency>,
) {
data class Currency(
@Json(name = "id") val id: String,
@Json(name = "code") val code: String, // this is an uppercase id
@Json(name = "name") val name: String,
@Json(name = "rateBTC") val rateBTC: String,
@Json(name = "unit") val unit: String, // $, €, ₽
@Json(name = "type") val type: String
)
data class Currency(
@Json(name = "id") val id: String,
@Json(name = "code") val code: String, // this is an uppercase id
@Json(name = "name") val name: String,
@Json(name = "rateBTC") val rateBTC: String,
@Json(name = "unit") val unit: String, // $, €, ₽
@Json(name = "type") val type: String,
)
}

View file

@ -0,0 +1,8 @@
package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json
//rates.keys = networkId's
data class RatesResponse(
@Json(name = "rates") val rates: Map<String, Double>,
)

View file

@ -6,15 +6,16 @@ data class UserTokensResponse(
@Json(name = "version") val version: Int = 0,
@Json(name = "group") val group: String? = null,
@Json(name = "sort") val sort: String? = null,
@Json(name = "tokens") val tokens: List<TokenBody> = emptyList(),
)
@Json(name = "tokens") val tokens: List<Token> = emptyList(),
) {
data class TokenBody(
@Json(name = "id") val id: String? = null,
@Json(name = "networkId") val networkId: String,
@Json(name = "derivationPath") val derivationPath: String? = null,
@Json(name = "name") val name: String,
@Json(name = "symbol") val symbol: String,
@Json(name = "decimals") val decimals: Int,
@Json(name = "contractAddress") val contractAddress: String?,
)
data class Token(
@Json(name = "id") val id: String? = null,
@Json(name = "networkId") val networkId: String,
@Json(name = "derivationPath") val derivationPath: String? = null,
@Json(name = "name") val name: String,
@Json(name = "symbol") val symbol: String,
@Json(name = "decimals") val decimals: Int,
@Json(name = "contractAddress") val contractAddress: String?,
)
}

View file

@ -72,6 +72,7 @@ android {
dependencies {
implementation(project(":core:datasource"))
implementation(project(":core:utils"))
implementation(project(":common"))
/** Tangem libraries */

View file

@ -1,7 +1,7 @@
package com.tangem.domain
import com.tangem.common.extensions.VoidCallback
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
/**
[REDACTED_AUTHOR]
@ -14,6 +14,6 @@ sealed interface DomainDialog {
val items: List<CoinsResponse.Coin.Network>,
val networkIdConverter: (String) -> String,
val onSelect: (CoinsResponse.Coin.Network) -> Unit,
val onClose: VoidCallback = {}
val onClose: VoidCallback = {},
) : DomainDialog
}

View file

@ -1,29 +0,0 @@
package com.tangem.domain.common.extensions
import com.tangem.common.services.Result
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.datasource.api.tangemTech.TangemTechService
suspend fun TangemTechService.getTokens(
contractAddress: String,
networkId: String? = null,
active: Boolean? = null,
): Result<CoinsResponse> = coins(
contractAddress = contractAddress,
networkIds = networkId,
active = active
)
suspend fun TangemTechService.getListOfCoins(
networkIds: List<String>,
active: Boolean? = null,
searchText: String? = null,
offset: Int? = null,
limit: Int? = null
): Result<CoinsResponse> = coins(
networkIds = networkIds.joinToString(","),
active = active,
searchText = searchText,
offset = offset,
limit = limit
)

View file

@ -1,15 +1,16 @@
package com.tangem.domain.features.addCustomToken
import com.tangem.common.services.Result
import com.tangem.domain.common.extensions.getTokens
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.datasource.api.tangemTech.TangemTechService
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
/**
[REDACTED_AUTHOR]
*/
class AddCustomTokenService(
private val tangemTechService: TangemTechService,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
private val supportedTokenNetworkIds: List<String>,
) {
@ -17,13 +18,17 @@ class AddCustomTokenService(
contractAddress: String,
networkId: String? = null,
active: Boolean? = null,
): Result<List<CoinsResponse.Coin>> {
val networksIds = selectNetworksForSearch(networkId)
val result = tangemTechService.getTokens(contractAddress, networksIds, active)
return when (result) {
is Result.Success -> {
): List<CoinsResponse.Coin> = withContext(dispatchers.io) {
runCatching {
tangemTechApi.getCoins(
contractAddress = contractAddress,
networkIds = selectNetworksForSearch(networkId),
active = active,
)
}
.onSuccess { response ->
var coinsList = mutableListOf<CoinsResponse.Coin>()
result.data.coins.forEach { coin ->
response.coins.forEach { coin ->
val networksWithTheSameAddress = coin.networks
.filter { it.contractAddress != null || it.decimalCount != null }
.filter { it.contractAddress?.equals(contractAddress, ignoreCase = true) == true }
@ -37,10 +42,13 @@ class AddCustomTokenService(
// https://tangem.slack.com/archives/GMXC6PP71/p1649672562078679
coinsList = mutableListOf(coinsList[0])
}
Result.Success(coinsList)
return@withContext coinsList
}
is Result.Failure -> result
}
.onFailure {
return@withContext emptyList()
}
throw IllegalStateException("Unreachable code because runCatching must return result")
}
private fun selectNetworksForSearch(networkId: String?): String {

View file

@ -2,13 +2,13 @@ package com.tangem.domain.features.addCustomToken.redux
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.DomainWrapped
import com.tangem.domain.common.form.Field
import com.tangem.domain.common.form.FieldId
import com.tangem.domain.features.addCustomToken.CustomCurrency
import com.tangem.domain.features.addCustomToken.CustomTokenFieldId
import com.tangem.datasource.api.tangemTech.CoinsResponse
import org.rekotlin.Action
/**

View file

@ -3,7 +3,7 @@ package com.tangem.domain.features.addCustomToken.redux
import android.webkit.ValueCallback
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.extensions.guard
import com.tangem.common.services.Result
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.AddCustomTokenError.Warning.PotentialScamToken
import com.tangem.domain.AddCustomTokenError.Warning.TokenAlreadyAdded
@ -56,7 +56,7 @@ import com.tangem.domain.redux.domainStore
import com.tangem.domain.redux.extensions.dispatchOnMain
import com.tangem.domain.redux.global.DomainGlobalAction
import com.tangem.domain.redux.global.DomainGlobalState
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@ -232,11 +232,13 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
}
if (state.screenState.derivationPath.isEnabled != derivationIsSupportedByNetwork) {
val action = Screen.UpdateTokenFields(listOf(
DerivationPath to state.screenState.derivationPath.copy(
isEnabled = derivationIsSupportedByNetwork,
val action = Screen.UpdateTokenFields(
listOf(
DerivationPath to state.screenState.derivationPath.copy(
isEnabled = derivationIsSupportedByNetwork,
),
),
))
)
dispatchOnMain(action)
}
}
@ -297,10 +299,12 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
}
}
dispatchOnMain(Warning.Replace(
remove = warningsRemove,
add = warningsAdd,
))
dispatchOnMain(
Warning.Replace(
remove = warningsRemove,
add = warningsAdd,
),
)
}
private suspend fun updateAddButton() {
@ -340,9 +344,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
}
}
private suspend fun requestInfoAboutToken(
contractAddress: String,
): List<CoinsResponse.Coin> {
private suspend fun requestInfoAboutToken(contractAddress: String): List<CoinsResponse.Coin> {
val tangemTechServiceManager = requireNotNull(hubState.tangemTechServiceManager)
dispatchOnMain(Screen.UpdateTokenFields(listOf(ContractAddress to ViewStates.TokenField(isLoading = true))))
@ -355,15 +357,8 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
// got the result faster than 500ms and the delay would only be the difference between them.
delay(500)
val foundTokensResult = tangemTechServiceManager.findToken(contractAddress, selectedNetworkId)
val result = when (foundTokensResult) {
is Result.Success -> foundTokensResult.data
is Result.Failure -> {
// val warning = Warning.Network.CheckAddressRequestError
// dispatchOnMain(Warning.Add(setOf(warning)))
emptyList()
}
}
val result = tangemTechServiceManager.findToken(contractAddress, selectedNetworkId)
dispatchOnMain(Screen.UpdateTokenFields(listOf(ContractAddress to ViewStates.TokenField(isLoading = false))))
return result
}
@ -431,10 +426,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
derivationStyle = hubState.cardDerivationStyle
)
private suspend fun fillTokenFields(
token: CoinsResponse.Coin,
coinNetwork: CoinsResponse.Coin.Network,
) {
private suspend fun fillTokenFields(token: CoinsResponse.Coin, coinNetwork: CoinsResponse.Coin.Network) {
val blockchain = Blockchain.fromNetworkId(coinNetwork.networkId) ?: Blockchain.Unknown
Network.setFieldValue(Field.Data(blockchain, false))
Name.setFieldValue(Field.Data(token.name, false))
@ -460,11 +452,13 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
private suspend fun enableDisableTokenDetailFields(isEnabled: Boolean = true) {
val state = hubState
val action = Screen.UpdateTokenFields(listOf(
Name to state.screenState.name.copy(isEnabled = isEnabled),
Symbol to state.screenState.symbol.copy(isEnabled = isEnabled),
Decimals to state.screenState.decimals.copy(isEnabled = isEnabled),
))
val action = Screen.UpdateTokenFields(
listOf(
Name to state.screenState.name.copy(isEnabled = isEnabled),
Symbol to state.screenState.symbol.copy(isEnabled = isEnabled),
Decimals to state.screenState.decimals.copy(isEnabled = isEnabled),
),
)
dispatchOnMain(action)
}
@ -597,8 +591,9 @@ private class AddCustomTokenReducer(
.filter { it.canHandleTokens() }
.map { it.toNetworkId() }
val tangemTechServiceManager = AddCustomTokenService(
tangemTechService = globalState.networkServices.tangemTechService,
supportedTokenNetworkIds = supportedTokenNetworkIds
tangemTechApi = globalState.networkServices.tangemTechService.api,
dispatchers = AppCoroutineDispatcherProvider(),
supportedTokenNetworkIds = supportedTokenNetworkIds,
)
val form = Form(AddCustomTokenState.createFormFields(card, CustomTokenType.Blockchain))
state.copy(
@ -745,5 +740,4 @@ private class AddCustomTokenReducer(
private fun updateFormState(state: AddCustomTokenState): AddCustomTokenState {
return state.copy(form = Form(state.form.fieldList))
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.domain.features.addCustomToken.redux
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.DomainWrapped
import com.tangem.domain.common.CardDTO
@ -37,7 +38,6 @@ import com.tangem.domain.features.addCustomToken.TokenDerivationPathField
import com.tangem.domain.features.addCustomToken.TokenField
import com.tangem.domain.redux.DomainState
import com.tangem.domain.redux.state.StringActionStateConverter
import com.tangem.datasource.api.tangemTech.CoinsResponse
import org.rekotlin.Action
import org.rekotlin.StateType

View file

@ -33,7 +33,7 @@ internal class SwapRepositoryImpl @Inject constructor(
override suspend fun getExchangeableTokens(networkId: String): List<Currency> {
return withContext(coroutineDispatcher.io) {
tokensConverter.convertList(tangemTechApi.coins(exchangeable = true, networkIds = networkId).coins)
tokensConverter.convertList(tangemTechApi.getCoins(exchangeable = true, networkIds = networkId).coins)
}
}

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.utils.converter.Converter
import javax.inject.Inject