diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt index 0e18c4018d..c70127f7e2 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt @@ -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 ) - fun List.toContracts(): List { return mapNotNull { Contract.fromJsonObject(it) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt index fbbaad9022..072992eeb8 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt @@ -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, offset: Int, - searchInput: String? = null + searchInput: String? = null, ): Result { - 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 { @@ -88,7 +97,6 @@ class LoadAvailableCoinsService( } } - data class LoadedCoins( val currencies: List, val moreAvailable: Boolean, diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/OldUserTokensRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/OldUserTokensRepository.kt index 2aa1dce1a7..4db0f6fb33 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/OldUserTokensRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/OldUserTokensRepository.kt @@ -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> = moshi.adapter( @@ -104,20 +104,27 @@ class OldUserTokensRepository( return blockchainNetworks } - private suspend fun getTokensIds(tokens: List): Map = coroutineScope { + private suspend fun getTokensIds(tokens: List): Map = 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 { diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt index 2fe9306d6f..b8b585e1ee 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt @@ -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, ) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt b/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt index 48f55ed575..3ac6babc72 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt @@ -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 { +/** Converter from domain model [Currency] to data model [UserTokensResponse.Token] */ +object CurrencyConverter : Converter { - override fun convert(value: Currency) = TokenBody( + override fun convert(value: Currency) = UserTokensResponse.Token( id = value.coinId, networkId = value.blockchain.toNetworkId(), derivationPath = value.derivationPath, diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index af6ab1607f..0ac39553eb 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -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 { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt index 00ea34457c..c67c02d950 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt @@ -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 { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt index 3b6375373a..45f88a8666 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt @@ -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.mapToUiModel(): List { + private fun List.mapToUiModel(): List { return this.map { FiatCurrency( code = it.code, diff --git a/app/src/main/java/com/tangem/tap/persistence/FiatCurrenciesPrefStorage.kt b/app/src/main/java/com/tangem/tap/persistence/FiatCurrenciesPrefStorage.kt index 1a65320a5e..a52f38f854 100644 --- a/app/src/main/java/com/tangem/tap/persistence/FiatCurrenciesPrefStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/FiatCurrenciesPrefStorage.kt @@ -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) { + fun save(currencies: List) { val json: String = converter.toJson(currencies) return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply() } - fun restore(): List { + fun restore(): List { 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() diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/Responses.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/Responses.kt deleted file mode 100644 index 64e625c180..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/Responses.kt +++ /dev/null @@ -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, - val total: Int, -) : TangemTechResponse { - - data class Coin( - val id: String, - val name: String, - val symbol: String, - val active: Boolean, - val networks: List = 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) : TangemTechResponse \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index e42f069cac..df8c21d2ea 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -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, diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt index f1d66ce518..e55103871c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt @@ -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 = withContext(Dispatchers.IO) { - performRequest { - api.coins( - contractAddress = contractAddress, - networkIds = networkIds, - active = active, - searchText = searchText, - offset = offset, - limit = limit, - ) - } - } - fun addHeaderInterceptors(interceptors: List) { headerInterceptors.removeAll(interceptors) headerInterceptors.addAll(interceptors) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CoinsResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CoinsResponse.kt new file mode 100644 index 0000000000..0a19554bf0 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CoinsResponse.kt @@ -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, + @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 = 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, + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt index 608b133f1a..64b69d3240 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt @@ -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 -) + @Json(name = "currencies") val currencies: List, +) { -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 -) \ No newline at end of file + 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, + ) +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/RateResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/RateResponse.kt new file mode 100644 index 0000000000..7355984410 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/RateResponse.kt @@ -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, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/UserTokensResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/UserTokensResponse.kt index 22c9d2fd4e..180deb01a0 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/UserTokensResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/UserTokensResponse.kt @@ -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 = emptyList(), -) + @Json(name = "tokens") val tokens: List = 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?, -) \ No newline at end of file + 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?, + ) +} \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index e365d69c25..93519446be 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -72,6 +72,7 @@ android { dependencies { implementation(project(":core:datasource")) + implementation(project(":core:utils")) implementation(project(":common")) /** Tangem libraries */ diff --git a/domain/src/main/java/com/tangem/domain/DomainDialog.kt b/domain/src/main/java/com/tangem/domain/DomainDialog.kt index 22e0ae8e28..c1f72a19de 100644 --- a/domain/src/main/java/com/tangem/domain/DomainDialog.kt +++ b/domain/src/main/java/com/tangem/domain/DomainDialog.kt @@ -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, val networkIdConverter: (String) -> String, val onSelect: (CoinsResponse.Coin.Network) -> Unit, - val onClose: VoidCallback = {} + val onClose: VoidCallback = {}, ) : DomainDialog } \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt b/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt deleted file mode 100644 index 925eaa5f82..0000000000 --- a/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt +++ /dev/null @@ -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 = coins( - contractAddress = contractAddress, - networkIds = networkId, - active = active - ) - -suspend fun TangemTechService.getListOfCoins( - networkIds: List, - active: Boolean? = null, - searchText: String? = null, - offset: Int? = null, - limit: Int? = null -): Result = coins( - networkIds = networkIds.joinToString(","), - active = active, - searchText = searchText, - offset = offset, - limit = limit - ) \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/AddCustomTokenService.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/AddCustomTokenService.kt index 98a63b6565..8015e7fc84 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/AddCustomTokenService.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/AddCustomTokenService.kt @@ -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, ) { @@ -17,13 +18,17 @@ class AddCustomTokenService( contractAddress: String, networkId: String? = null, active: Boolean? = null, - ): Result> { - val networksIds = selectNetworksForSearch(networkId) - val result = tangemTechService.getTokens(contractAddress, networksIds, active) - return when (result) { - is Result.Success -> { + ): List = withContext(dispatchers.io) { + runCatching { + tangemTechApi.getCoins( + contractAddress = contractAddress, + networkIds = selectNetworksForSearch(networkId), + active = active, + ) + } + .onSuccess { response -> var coinsList = mutableListOf() - 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 { diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenAction.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenAction.kt index 3a5946f963..cc41cdb3d4 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenAction.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenAction.kt @@ -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 /** diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt index 3a48aa34a7..b0ffab36b3 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt @@ -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("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("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("AddCustomT } } - private suspend fun requestInfoAboutToken( - contractAddress: String, - ): List { + private suspend fun requestInfoAboutToken(contractAddress: String): List { val tangemTechServiceManager = requireNotNull(hubState.tangemTechServiceManager) dispatchOnMain(Screen.UpdateTokenFields(listOf(ContractAddress to ViewStates.TokenField(isLoading = true)))) @@ -355,15 +357,8 @@ internal class AddCustomTokenHub : BaseStoreHub("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("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("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)) } - } \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt index 978232de57..ad0be88966 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt @@ -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 diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt index 088a47045f..36e89a8e56 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt @@ -33,7 +33,7 @@ internal class SwapRepositoryImpl @Inject constructor( override suspend fun getExchangeableTokens(networkId: String): List { return withContext(coroutineDispatcher.io) { - tokensConverter.convertList(tangemTechApi.coins(exchangeable = true, networkIds = networkId).coins) + tokensConverter.convertList(tangemTechApi.getCoins(exchangeable = true, networkIds = networkId).coins) } } diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt index 11596db8bc..c78b8b3638 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt @@ -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