Updated on 2026-08-14

This commit is contained in:
Tangem 2022-11-29 22:29:19 +03:00
parent 0bbfef1bc7
commit e47b11f29e
8 changed files with 173 additions and 24 deletions

View file

@ -42,7 +42,7 @@ interface OneInchApi {
@GET("approve/transaction")
suspend fun approveTransaction(
@Query("tokenAddress") tokenAddress: String,
@Query("amount") amount: String?,
@Query("amount") amount: String? = null,
): ApproveCalldataResponse
/**
@ -118,14 +118,14 @@ interface OneInchApi {
@Query("fromTokenAddress") fromTokenAddress: String,
@Query("toTokenAddress") toTokenAddress: String,
@Query("amount") amount: String,
@Query("protocols") protocols: String?,
@Query("fee") fee: String?,
@Query("gasLimit") gasLimit: String?,
@Query("connectorTokens") connectorTokens: String?,
@Query("complexityLevel") complexityLevel: String?,
@Query("mainRouteParts") mainRouteParts: String?,
@Query("parts") parts: String?,
@Query("gasPrice") gasPrice: String?,
@Query("protocols") protocols: String? = null,
@Query("fee") fee: String? = null,
@Query("gasLimit") gasLimit: String? = null,
@Query("connectorTokens") connectorTokens: String? = null,
@Query("complexityLevel") complexityLevel: String? = null,
@Query("mainRouteParts") mainRouteParts: String? = null,
@Query("parts") parts: String? = null,
@Query("gasPrice") gasPrice: String? = null,
): QuoteResponse
/**
@ -180,21 +180,21 @@ interface OneInchApi {
@Query("amount") amount: String,
@Query("fromAddress") fromAddress: String,
@Query("slippage") slippage: Int,
@Query("protocols") protocols: String?,
@Query("destReceiver") destinationAddress: String?,
@Query("referrerAddress") referrerAddress: String?,
@Query("fee") fee: String?,
@Query("disableEstimate") disableEstimate: Boolean?,
@Query("permit") permit: String?,
@Query("compatibilityMode") compatibilityMode: Boolean?,
@Query("burnChi") burnChi: Boolean?,
@Query("allowPartialFill") allowPartialFill: Boolean?,
@Query("parts") parts: String?,
@Query("mainRouteParts") mainRouteParts: String?,
@Query("connectorTokens") connectorTokens: String?,
@Query("complexityLevel") complexityLevel: String?,
@Query("gasLimit") gasLimit: String?,
@Query("gasPrice") gasPrice: String?,
@Query("protocols") protocols: String? = null,
@Query("destReceiver") destinationAddress: String? = null,
@Query("referrerAddress") referrerAddress: String? = null,
@Query("fee") fee: String? = null,
@Query("disableEstimate") disableEstimate: Boolean? = null,
@Query("permit") permit: String? = null,
@Query("compatibilityMode") compatibilityMode: Boolean? = null,
@Query("burnChi") burnChi: Boolean? = null,
@Query("allowPartialFill") allowPartialFill: Boolean? = null,
@Query("parts") parts: String? = null,
@Query("mainRouteParts") mainRouteParts: String? = null,
@Query("connectorTokens") connectorTokens: String? = null,
@Query("complexityLevel") complexityLevel: String? = null,
@Query("gasLimit") gasLimit: String? = null,
@Query("gasPrice") gasPrice: String? = null,
): SwapResponse
//endregion Swap
}

View file

@ -0,0 +1,45 @@
package com.tangem.feature.swap
import com.tangem.datasource.api.oneinch.OneInchApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.feature.swap.converters.QuotesConverter
import com.tangem.feature.swap.converters.TokensConverter
import com.tangem.feature.swap.domain.SwapRepository
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import javax.inject.Inject
class SwapRepositoryImpl @Inject constructor(
private val tangemTechApi: TangemTechApi,
private val oneInchApi: OneInchApi,
private val tokensConverter: TokensConverter,
private val quotesConverter: QuotesConverter,
private val coroutineDispatcher: CoroutineDispatcherProvider,
) : SwapRepository {
override suspend fun getExchangeableTokens(networkId: String): List<Currency> {
return withContext(coroutineDispatcher.io) {
tokensConverter.convertList(tangemTechApi.coins(exchangeable = true, networkIds = networkId).coins)
}
}
override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): QuoteModel {
return withContext(coroutineDispatcher.io) {
quotesConverter.convert(
oneInchApi.quote(
fromTokenAddress = fromTokenAddress,
toTokenAddress = toTokenAddress,
amount = amount,
),
)
}
}
override suspend fun addressForTrust(): String {
return withContext(coroutineDispatcher.io) {
oneInchApi.approveSpender().address
}
}
}

View file

@ -0,0 +1,16 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.oneinch.models.QuoteResponse
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.utils.converter.Converter
class QuotesConverter : Converter<QuoteResponse, QuoteModel> {
override fun convert(value: QuoteResponse): QuoteModel {
return QuoteModel(
fromTokenAmount = value.fromTokenAmount,
toTokenAmount = value.toTokenAmount,
estimatedGas = value.estimatedGas,
)
}
}

View file

@ -0,0 +1,32 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.tangemTech.CoinsResponse
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.utils.converter.Converter
import javax.inject.Inject
class TokensConverter @Inject constructor() : Converter<CoinsResponse.Coin, Currency> {
override fun convert(value: CoinsResponse.Coin): Currency {
val network = value.networks.first()
return if (network.contractAddress != null && network.decimalCount != null) {
Currency.NonNativeToken(
id = value.id,
name = value.name,
symbol = value.symbol,
networkId = network.networkId,
contractAddress = network.contractAddress!!,
decimalCount = network.decimalCount!!.intValueExact(),
logoUrl = "",//todo add logo
)
} else {
Currency.NativeToken(
id = value.id,
name = value.name,
symbol = value.symbol,
networkId = network.networkId,
logoUrl = "", //todo add logo
)
}
}
}

View file

@ -0,0 +1,4 @@
package com.tangem.feature.swap.domain
interface SwapInteractor {
}

View file

@ -0,0 +1,17 @@
package com.tangem.feature.swap.domain
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
interface SwapRepository {
suspend fun getExchangeableTokens(networkId: String): List<Currency>
suspend fun findBestQuote(
fromTokenAddress: String,
toTokenAddress: String,
amount: String,
): QuoteModel
suspend fun addressForTrust(): String
}

View file

@ -0,0 +1,28 @@
package com.tangem.feature.swap.domain.models
sealed class Currency(
open val id: String,
open val name: String,
open val symbol: String,
open val networkId: String,
open val logoUrl: String,
) {
data class NativeToken(
override val id: String,
override val name: String,
override val symbol: String,
override val networkId: String,
override val logoUrl: String,
) : Currency(id, name, symbol, networkId, logoUrl)
data class NonNativeToken(
override val id: String,
override val name: String,
override val symbol: String,
override val networkId: String,
override val logoUrl: String,
val contractAddress: String,
val decimalCount: Int,
) : Currency(id, name, symbol, networkId, logoUrl)
}

View file

@ -0,0 +1,7 @@
package com.tangem.feature.swap.domain.models
data class QuoteModel(
val fromTokenAmount: String,
val toTokenAmount: String,
val estimatedGas: Int
)