Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-20 14:28:16 +02:00
parent a74ee9640c
commit d574159e14
10 changed files with 97 additions and 40 deletions

View file

@ -46,6 +46,7 @@ internal class SwapRepositoryImpl @Inject constructor(
private val swapConverter = SwapConverter()
private val leastTokenInfoConverter = LeastTokenInfoConverter()
private val swapPairInfoConverter = SwapPairInfoConverter()
private val rateTypeConverter = RateTypeConverter()
override suspend fun getPairs(
initialCurrency: LeastTokenInfo,
@ -257,6 +258,31 @@ internal class SwapRepositoryImpl @Inject constructor(
return oneInchApiFactory.getApi(networkId)
}
override suspend fun getExchangeQuote(
fromContractAddress: String,
fromNetwork: String,
toContractAddress: String,
toNetwork: String,
fromAmount: BigDecimal,
providerId: Int,
rateType: RateType
): ExchangeQuote {
val response = tangemExpressApi.getExchangeQuote(
fromContractAddress,
fromNetwork,
toContractAddress,
toNetwork,
fromAmount,
providerId,
rateTypeConverter.convertBack(rateType)
).getOrThrow()
return ExchangeQuote(
toAmount = response.toAmount,
allowanceContract = response.allowanceContract
)
}
companion object {
// TODO("get this ids from blockchain enum later")
private const val OPTIMISM_ID = "optimistic-ethereum"

View file

@ -0,0 +1,22 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.express.models.response.RateType
import com.tangem.utils.converter.TwoWayConverter
import com.tangem.feature.swap.domain.models.domain.RateType as RateTypeDomain
class RateTypeConverter : TwoWayConverter<RateType, RateTypeDomain> {
override fun convert(value: RateType): RateTypeDomain {
return when (value) {
RateType.FIXED -> RateTypeDomain.FIXED
RateType.FLOAT -> RateTypeDomain.FLOAT
}
}
override fun convertBack(value: RateTypeDomain): RateType {
return when (value) {
RateTypeDomain.FIXED -> RateType.FIXED
RateTypeDomain.FLOAT -> RateType.FLOAT
}
}
}

View file

@ -1,16 +1,16 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.express.models.response.RateType
import com.tangem.datasource.api.express.models.response.SwapPair
import com.tangem.datasource.api.express.models.response.SwapPairProvider
import com.tangem.feature.swap.domain.models.domain.LeastTokenInfo
import com.tangem.feature.swap.domain.models.domain.SwapPairLeast as SwapPairDomain
import com.tangem.feature.swap.domain.models.domain.SwapPairProvider as SwapPairProviderDomain
import com.tangem.feature.swap.domain.models.domain.RateType as RateTypeDomain
import com.tangem.feature.swap.domain.models.domain.SwapProvider as SwapPairProviderDomain
import com.tangem.utils.converter.Converter
class SwapPairInfoConverter : Converter<SwapPair, SwapPairDomain> {
private val rateTypeConverter = RateTypeConverter()
override fun convert(value: SwapPair): SwapPairDomain {
return SwapPairDomain(
from = LeastTokenInfo(
@ -30,14 +30,8 @@ class SwapPairInfoConverter : Converter<SwapPair, SwapPairDomain> {
private fun convertProvider(swapPairProvider: SwapPairProvider): SwapPairProviderDomain {
return SwapPairProviderDomain(
providerId = swapPairProvider.providerId,
rateTypes = swapPairProvider.rateTypes.map { convertRateType(it) },
rateTypes = swapPairProvider.rateTypes.map { rateTypeConverter.convert(it) },
)
}
private fun convertRateType(rateType: RateType): RateTypeDomain {
return when (rateType) {
RateType.FIXED -> RateTypeDomain.FIXED
RateType.FLOAT -> RateTypeDomain.FLOAT
}
}
}

View file

@ -27,7 +27,7 @@ internal class DefaultBlockchainInteractor @Inject constructor(
return if (token is CryptoCurrency.Token) {
token.decimals
} else {
transactionManager.getNativeTokenDecimals(token.network.id.value)
transactionManager.getNativeTokenDecimals(token.network.backendId)
}
}
}

View file

@ -107,15 +107,17 @@ internal class SwapInteractorImpl @Inject constructor(
tokenInfoForFilter(it).network == currency.network.backendId
}
val availableCryptoCurrencies = filteredPairs.mapNotNull {
findCryptoCurrencyStatusByLeastInfo(tokenInfoForAvailable(it), cryptoCurrenciesList)
val availableCryptoCurrencies = filteredPairs.mapNotNull { pair ->
val status = findCryptoCurrencyStatusByLeastInfo(tokenInfoForAvailable(pair), cryptoCurrenciesList)
status?.let { CryptoCurrencySwapInfo(it, pair.providers) }
}
val unavailableCryptoCurrencies = cryptoCurrenciesList - availableCryptoCurrencies.toSet()
val unavailableCryptoCurrencies =
(cryptoCurrenciesList - availableCryptoCurrencies.map { it.currencyStatus }.toSet())
return CurrenciesGroup(
available = availableCryptoCurrencies,
unavailable = unavailableCryptoCurrencies,
unavailable = unavailableCryptoCurrencies.map { CryptoCurrencySwapInfo(it, emptyList()) }
)
}
@ -415,7 +417,7 @@ internal class SwapInteractorImpl @Inject constructor(
return if (token is CryptoCurrency.Token) {
token.decimals
} else {
transactionManager.getNativeTokenDecimals(token.network.id.value)
transactionManager.getNativeTokenDecimals(token.network.backendId)
}
}

View file

@ -61,4 +61,14 @@ interface SwapRepository {
currency: CryptoCurrency,
amount: BigDecimal?,
): String
suspend fun getExchangeQuote(
fromContractAddress: String,
fromNetwork: String,
toContractAddress: String,
toNetwork: String,
fromAmount: BigDecimal,
providerId: Int,
rateType: RateType,
) : ExchangeQuote
}

View file

@ -0,0 +1,8 @@
package com.tangem.feature.swap.domain.models.domain
import java.math.BigDecimal
data class ExchangeQuote(
val toAmount: BigDecimal,
val allowanceContract: String?
)

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.domain.models.domain
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
/**
* Domain layer representation of SwapPair data network model.
@ -12,20 +12,12 @@ import com.tangem.domain.tokens.model.CryptoCurrency
data class SwapPairLeast(
val from: LeastTokenInfo,
val to: LeastTokenInfo,
val providers: List<SwapPairProvider>,
val providers: List<SwapProvider>,
)
/**
* Enriched model of swap pair data. Contains full CryptoCurrency models instead of least info.
*
* @property from CryptoCurrency we want to change
* @property to CryptoCurrency we want to exchange for
* @property providers Exchange providers
*/
data class SwapPair(
val from: CryptoCurrency,
val to: CryptoCurrency,
val providers: List<SwapPairProvider>,
data class CryptoCurrencySwapInfo(
val currencyStatus: CryptoCurrencyStatus,
val providers: List<SwapProvider>
)
/**
@ -34,7 +26,7 @@ data class SwapPair(
* @property providerId provider id
* @property rateTypes supported rate types
*/
data class SwapPairProvider(
data class SwapProvider(
val providerId: Int,
val rateTypes: List<RateType>,
)

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.domain.models.ui
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.domain.CryptoCurrencySwapInfo
data class TokensDataStateExpress(
val fromGroup: CurrenciesGroup,
@ -9,8 +9,8 @@ data class TokensDataStateExpress(
)
data class CurrenciesGroup(
val available: List<CryptoCurrencyStatus>,
val unavailable: List<CryptoCurrencyStatus>,
val available: List<CryptoCurrencySwapInfo>,
val unavailable: List<CryptoCurrencySwapInfo>,
)
data class FoundTokensStateExpress(

View file

@ -132,14 +132,17 @@ internal class SwapViewModel @Inject constructor(
runCatching(dispatchers.io) {
swapInteractor.getTokensDataState(initialCryptoCurrency)
}.onSuccess { state ->
// dataState = dataState.copy(
// )
dataState = dataState.copy(
fromCryptoCurrency = initialCryptoCurrency,
toCryptoCurrency = state.toGroup.available.first().currencyStatus.currency
)
// updateTokensState(dataState = state.foundTokensState)
// startLoadingQuotes(
// fromToken = state.preselectTokens.fromToken,
// toToken = state.preselectTokens.toToken,
// amount = lastAmount.value,
// )
startLoadingQuotes(
fromToken = initialCryptoCurrency,
toToken = state.toGroup.available.first().currencyStatus.currency,
amount = lastAmount.value,
)
}.onFailure {
Timber.tag(loggingTag).e(it)
}