diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt index 2d62fb3630..6144d6ad9e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt @@ -42,9 +42,9 @@ interface TangemExpressApi { @Query("fromNetwork") fromNetwork: String, @Query("toContractAddress") toContractAddress: String, @Query("toNetwork") toNetwork: String, - @Query("fromAmount") fromAmount: BigDecimal, - @Query("providerId") providerId: Int, - @Query("rateType") rateType: RateType, + @Query("fromAmount") fromAmount: String, + @Query("providerId") providerId: String, + @Query("rateType") rateType: String, @Query("toAddress") toAddress: String, ): ApiResponse diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt index 3083bdfd0b..72deee1a57 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt @@ -4,8 +4,17 @@ import com.squareup.moshi.Json import java.math.BigDecimal data class ExchangeDataResponse( + @Json(name = "fromAmount") + val fromAmount: String, + + @Json(name = "fromDecimals") + val fromDecimals: Int, + @Json(name = "toAmount") - val toAmount: BigDecimal, + val toAmount: String, + + @Json(name = "toDecimals") + val toDecimals: Int, @Json(name = "txType") val txType: TxType, diff --git a/features/learn2earn/impl/build.gradle.kts b/features/learn2earn/impl/build.gradle.kts index dcb142ae2d..b9fb7f48a6 100644 --- a/features/learn2earn/impl/build.gradle.kts +++ b/features/learn2earn/impl/build.gradle.kts @@ -22,7 +22,6 @@ dependencies { implementation(project(":data:common")) implementation(project(":libs:auth")) implementation(project(":libs:crypto")) - implementation(projects.domain.tokens.models) implementation(deps.material) 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 72b4687f50..3571784929 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 @@ -49,7 +49,7 @@ internal class SwapRepositoryImpl @Inject constructor( ) : SwapRepository { private val tokensConverter = TokensConverter() - private val swapConverter = SwapConverter() + private val expressDataConverter = ExpressDataConverter() private val leastTokenInfoConverter = LeastTokenInfoConverter() private val swapPairInfoConverter = SwapPairInfoConverter() private val cryptoCurrencyFactory = CryptoCurrencyFactory() @@ -164,8 +164,8 @@ internal class SwapRepositoryImpl @Inject constructor( toTokenAmount = createFromAmountWithOffset(response.toAmount, response.toDecimals), ), ) - } catch (ex: OneIncResponseException) { - AggregatedSwapDataModel(null, mapErrors(ex.data.description)) + } catch (ex: Exception) { + AggregatedSwapDataModel(null, mapErrors(ex.message)) } } } @@ -176,31 +176,33 @@ internal class SwapRepositoryImpl @Inject constructor( } } - override suspend fun prepareSwapTransaction( - networkId: String, - fromTokenAddress: String, - toTokenAddress: String, - amount: String, - fromWalletAddress: String, - slippage: Int, + override suspend fun getExchangeData( + fromContractAddress: String, + fromNetwork: String, + toContractAddress: String, + toNetwork: String, + fromAmount: String, + providerId: String, + rateType: RateType, + toAddress: String, ): AggregatedSwapDataModel { return withContext(coroutineDispatcher.io) { try { - val swapResponse = oneInchErrorsHandler.handleOneInchResponse( - getOneInchApi(networkId).swap( - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, - amount = amount, - fromAddress = fromWalletAddress, - slippage = slippage, - referrerAddress = configManager.config.swapReferrerAccount?.address, - fee = configManager.config.swapReferrerAccount?.fee, - ), + val response = tangemExpressApi.getExchangeData( + fromContractAddress = fromContractAddress, + fromNetwork = fromNetwork, + toContractAddress = toContractAddress, + toNetwork = toNetwork, + fromAmount = fromAmount, + providerId = providerId, + rateType = rateType.name.lowercase(), + toAddress = toAddress + ).getOrThrow() + AggregatedSwapDataModel( + dataModel = expressDataConverter.convert(response) ) - - AggregatedSwapDataModel(swapConverter.convert(swapResponse)) - } catch (ex: OneIncResponseException) { - AggregatedSwapDataModel(null, mapErrors(ex.data.description)) + } catch (ex: Exception) { + AggregatedSwapDataModel(null, mapErrors(ex.message)) } } } @@ -280,31 +282,6 @@ internal class SwapRepositoryImpl @Inject constructor( return oneInchApiFactory.getApi(networkId) } - override suspend fun getExchangeQuote( - fromContractAddress: String, - fromNetwork: String, - toContractAddress: String, - toNetwork: String, - fromAmount: String, - providerId: String, - rateType: RateType, - ): ExchangeQuote { - val response = tangemExpressApi.getExchangeQuote( - fromContractAddress, - fromNetwork, - toContractAddress, - toNetwork, - fromAmount, - providerId, - rateType.name.lowercase(), - ).getOrThrow() - - return ExchangeQuote( - toAmount = response.toAmount, - allowanceContract = response.allowanceContract, - ) - } - override fun getNativeTokenForNetwork(networkId: String): CryptoCurrency { val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" } diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt new file mode 100644 index 0000000000..0c4278683f --- /dev/null +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt @@ -0,0 +1,41 @@ +package com.tangem.feature.swap.converters + +import com.tangem.datasource.api.express.models.response.ExchangeDataResponse +import com.tangem.datasource.api.express.models.response.TxType +import com.tangem.feature.swap.domain.models.createFromAmountWithOffset +import com.tangem.feature.swap.domain.models.domain.ExpressTransactionModel +import com.tangem.feature.swap.domain.models.domain.SwapDataModel +import com.tangem.utils.converter.Converter + +class ExpressDataConverter : Converter { + + override fun convert(value: ExchangeDataResponse): SwapDataModel { + return SwapDataModel( + toTokenAmount = createFromAmountWithOffset(value.toAmount, value.toDecimals), + transaction = convertTransaction(value), + ) + } + + private fun convertTransaction(transactionDto: ExchangeDataResponse): ExpressTransactionModel { + return if (transactionDto.txType == TxType.SWAP) { + ExpressTransactionModel.DEX( + fromAmount = createFromAmountWithOffset(transactionDto.fromAmount, transactionDto.fromDecimals), + toAmount = createFromAmountWithOffset(transactionDto.toAmount, transactionDto.toDecimals), + txId = transactionDto.txId, + txTo = transactionDto.txTo, + txFrom = requireNotNull(transactionDto.txFrom), + txData = requireNotNull(transactionDto.txData) + ) + } else { + ExpressTransactionModel.CEX( + fromAmount = createFromAmountWithOffset(transactionDto.fromAmount, transactionDto.fromDecimals), + toAmount = createFromAmountWithOffset(transactionDto.toAmount, transactionDto.toDecimals), + txId = transactionDto.txId, + txTo = transactionDto.txTo, + externalTxId = requireNotNull(transactionDto.externalTxId), + externalTxUrl = requireNotNull(transactionDto.externalTxUrl), + ) + } + } + +} \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt deleted file mode 100644 index 3c8c1003ec..0000000000 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.tangem.feature.swap.converters - -import com.tangem.datasource.api.oneinch.models.SwapResponse -import com.tangem.datasource.api.oneinch.models.TransactionDto -import com.tangem.feature.swap.domain.models.createFromAmountWithOffset -import com.tangem.feature.swap.domain.models.domain.SwapDataModel -import com.tangem.feature.swap.domain.models.domain.TransactionModel -import com.tangem.utils.converter.Converter - -class SwapConverter : Converter { - - override fun convert(value: SwapResponse): SwapDataModel { - return SwapDataModel( - toTokenAmount = createFromAmountWithOffset(value.toTokenAmount, value.toToken.decimals), - transaction = convertTransaction(value.transaction), - ) - } - - private fun convertTransaction(transactionDto: TransactionDto): TransactionModel { - return TransactionModel( - fromWalletAddress = transactionDto.fromAddress, - toWalletAddress = transactionDto.toAddress, - data = transactionDto.data, - value = transactionDto.value, - gasPrice = transactionDto.gasPrice, - gas = transactionDto.gas, - ) - } -} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 5c185a5cff..67be5cd7a5 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -286,8 +286,8 @@ internal class SwapInteractorImpl @Inject constructor( currencyToSend = swapCurrencyConverter.convert(currencyToSend), feeAmount = fee.feeValue, gasLimit = fee.gasLimit, - destinationAddress = swapStateData.swapModel.transaction.toWalletAddress, - dataToSign = swapStateData.swapModel.transaction.data, + destinationAddress = swapStateData.swapModel.transaction.txTo, + dataToSign = (swapStateData.swapModel.transaction as ExpressTransactionModel.DEX).txData, ), isSwap = true, derivationPath = derivationPath, @@ -518,13 +518,21 @@ internal class SwapInteractorImpl @Inject constructor( amount: SwapAmount, selectedFee: FeeType, ): SwapState { - repository.prepareSwapTransaction( - networkId = networkId, - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, - amount = amount.toStringWithRightOffset(), - slippage = DEFAULT_SLIPPAGE, - fromWalletAddress = getWalletAddress(networkId), + repository.getExchangeData( + fromContractAddress = fromToken.currency.getContractAddress(), + fromNetwork = fromToken.currency.network.backendId, + toContractAddress = toToken.currency.getContractAddress(), + toNetwork = toToken.currency.network.backendId, + fromAmount = amount.toStringWithRightOffset(), + providerId = "1", //TODO + rateType = RateType.FLOAT, + toAddress = toToken.value.networkAddress?.defaultAddress ?: "" + // networkId = networkId, + // fromTokenAddress = fromTokenAddress, + // toTokenAddress = toTokenAddress, + // amount = amount.toStringWithRightOffset(), + // slippage = DEFAULT_SLIPPAGE, + // fromWalletAddress = getWalletAddress(networkId), ).let { val swapData = it.dataModel if (swapData != null) { @@ -532,9 +540,9 @@ internal class SwapInteractorImpl @Inject constructor( networkId = networkId, amountToSend = amount.value, currencyToSend = swapCurrencyConverter.convert(fromToken.currency), - destinationAddress = swapData.transaction.toWalletAddress, + destinationAddress = swapData.transaction.txTo, increaseBy = INCREASE_GAS_LIMIT_BY, - data = swapData.transaction.data, + data = (swapData.transaction as ExpressTransactionModel.DEX).txData, derivationPath = derivationPath, ) val txFeeState = proxyFeesToFeeState(networkId, feeData) 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 index 31863dc852..d919661845 100644 --- 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 @@ -32,16 +32,6 @@ interface SwapRepository { */ suspend fun addressForTrust(networkId: String): String - @Suppress("LongParameterList") - suspend fun prepareSwapTransaction( - networkId: String, - fromTokenAddress: String, - toTokenAddress: String, - amount: String, - fromWalletAddress: String, - slippage: Int, - ): AggregatedSwapDataModel - /** * Returns a tangem fee for swap in percents * Example: 0.35% @@ -67,7 +57,7 @@ interface SwapRepository { ): String @Suppress("LongParameterList") - suspend fun getExchangeQuote( + suspend fun getExchangeData( fromContractAddress: String, fromNetwork: String, toContractAddress: String, @@ -75,7 +65,8 @@ interface SwapRepository { fromAmount: String, providerId: String, rateType: RateType, - ): ExchangeQuote + toAddress: String, + ): AggregatedSwapDataModel fun getNativeTokenForNetwork(networkId: String): CryptoCurrency } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt index fbcbeb51b0..a00be2a2bc 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt @@ -1,20 +1,10 @@ package com.tangem.feature.swap.domain.models sealed class DataError { - object NoError : DataError() - data class UnknownError(val message: String) : DataError() - object InsufficientLiquidity : DataError() + object UnknownError : DataError() + data class Error(val message: String) : DataError() } fun mapErrors(error: String?): DataError { - return if (error == null) { - DataError.NoError - } else { - when (error) { - INSUFFICIENT_LIQUIDITY_ERROR -> DataError.InsufficientLiquidity - else -> DataError.UnknownError(error) - } - } -} - -private const val INSUFFICIENT_LIQUIDITY_ERROR = "insufficient liquidity" \ No newline at end of file + return error?.let { DataError.Error(it) } ?: DataError.UnknownError +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/AggregatedSwapDataModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/AggregatedSwapDataModel.kt index 317b0da94f..45a895181e 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/AggregatedSwapDataModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/AggregatedSwapDataModel.kt @@ -11,5 +11,5 @@ import com.tangem.feature.swap.domain.models.DataError */ data class AggregatedSwapDataModel( val dataModel: T?, - val error: DataError = DataError.NoError, + val error: DataError = DataError.UnknownError, ) \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExpressTransactionModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExpressTransactionModel.kt new file mode 100644 index 0000000000..30271929e7 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExpressTransactionModel.kt @@ -0,0 +1,30 @@ +package com.tangem.feature.swap.domain.models.domain + +import com.tangem.feature.swap.domain.models.SwapAmount + +sealed class ExpressTransactionModel { + + abstract val fromAmount: SwapAmount + abstract val toAmount: SwapAmount + abstract val txId: String + abstract val txTo: String + + data class DEX( + override val fromAmount: SwapAmount, + override val toAmount: SwapAmount, + override val txId: String, + override val txTo: String, + val txFrom: String, + val txData: String, + ): ExpressTransactionModel() + + data class CEX( + override val fromAmount: SwapAmount, + override val toAmount: SwapAmount, + override val txId: String, + override val txTo: String, + val externalTxId: String, + val externalTxUrl: String, + ): ExpressTransactionModel() + +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapDataModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapDataModel.kt index 7c15701329..8b2927968f 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapDataModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapDataModel.kt @@ -2,13 +2,7 @@ package com.tangem.feature.swap.domain.models.domain import com.tangem.feature.swap.domain.models.SwapAmount -/** - * Swap transaction model - * - * @property toTokenAmount amount "target" token - * @property transaction info about transaction - */ data class SwapDataModel( val toTokenAmount: SwapAmount, - val transaction: TransactionModel, + val transaction: ExpressTransactionModel, ) \ No newline at end of file diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index e7623069ab..6d740e3fa6 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -574,7 +574,7 @@ internal class StateBuilder( // todo use if needed later // DataError.InsufficientLiquidity -> TODO() // DataError.NoError -> TODO() - is DataError.UnknownError -> addWarning(uiState, error.message, true, onClick) + is DataError.Error -> addWarning(uiState, error.message, true, onClick) else -> addWarning(uiState, null, false) {} } } diff --git a/libs/crypto/build.gradle.kts b/libs/crypto/build.gradle.kts index f8a413d31d..248cc20bd1 100644 --- a/libs/crypto/build.gradle.kts +++ b/libs/crypto/build.gradle.kts @@ -1,12 +1,10 @@ plugins { - alias(deps.plugins.android.library) - alias(deps.plugins.kotlin.android) + alias(deps.plugins.kotlin.jvm) id("configuration") } dependencies { + /** Coroutines */ implementation(deps.kotlin.coroutines) - implementation(projects.domain.tokens.models) - } \ No newline at end of file