From e47b11f29e77cde521035b2d7d7a30919f1cb4a5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 29 Nov 2022 22:29:19 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../datasource/api/oneinch/OneInchApi.kt | 48 +++++++++---------- .../tangem/feature/swap/SwapRepositoryImpl.kt | 45 +++++++++++++++++ .../swap/converters/QuotesConverter.kt | 16 +++++++ .../swap/converters/TokensConverter.kt | 32 +++++++++++++ .../feature/swap/domain/SwapInteractor.kt | 4 ++ .../feature/swap/domain/SwapRepository.kt | 17 +++++++ .../feature/swap/domain/models/Currency.kt | 28 +++++++++++ .../feature/swap/domain/models/QuoteModel.kt | 7 +++ 8 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt create mode 100644 features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt create mode 100644 features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt index 5ce908280b..774d001e04 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt @@ -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 } \ No newline at end of file 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 new file mode 100644 index 0000000000..aab22f9b8c --- /dev/null +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt @@ -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 { + 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 + } + } +} \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt new file mode 100644 index 0000000000..52723c6596 --- /dev/null +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt @@ -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 { + + override fun convert(value: QuoteResponse): QuoteModel { + return QuoteModel( + fromTokenAmount = value.fromTokenAmount, + toTokenAmount = value.toTokenAmount, + estimatedGas = value.estimatedGas, + ) + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..c5414d666c --- /dev/null +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt @@ -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 { + + 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 + ) + } + } +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt new file mode 100644 index 0000000000..eebb325e5e --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -0,0 +1,4 @@ +package com.tangem.feature.swap.domain + +interface SwapInteractor { +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt new file mode 100644 index 0000000000..5aea22d2b8 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt @@ -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 + + suspend fun findBestQuote( + fromTokenAddress: String, + toTokenAddress: String, + amount: String, + ): QuoteModel + + suspend fun addressForTrust(): String +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt new file mode 100644 index 0000000000..05fe0cad3b --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt @@ -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) +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt new file mode 100644 index 0000000000..e71378fd22 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt @@ -0,0 +1,7 @@ +package com.tangem.feature.swap.domain.models + +data class QuoteModel( + val fromTokenAmount: String, + val toTokenAmount: String, + val estimatedGas: Int +) \ No newline at end of file