Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-07 19:19:49 +03:00
parent 38f76ed5b3
commit bff39be461
11 changed files with 31 additions and 46 deletions

View file

@ -117,8 +117,8 @@ interface OneInchApi {
*/
@GET("quote")
suspend fun quote(
@Query("fromTokenAddress") fromTokenAddress: String,
@Query("toTokenAddress") toTokenAddress: String,
@Query("src") fromTokenAddress: String,
@Query("dst") toTokenAddress: String,
@Query("amount") amount: String,
@Query("protocols") protocols: String? = null,
@Query("fee") fee: String? = null,
@ -128,6 +128,7 @@ interface OneInchApi {
@Query("mainRouteParts") mainRouteParts: String? = null,
@Query("parts") parts: String? = null,
@Query("gasPrice") gasPrice: String? = null,
@Query("includeTokensInfo") includeTokensInfo: Boolean = true,
): Response<QuoteResponse>
/**
@ -178,18 +179,18 @@ interface OneInchApi {
*/
@GET("swap")
suspend fun swap(
@Query("fromTokenAddress") fromTokenAddress: String,
@Query("toTokenAddress") toTokenAddress: String,
@Query("src") fromTokenAddress: String,
@Query("dst") toTokenAddress: String,
@Query("amount") amount: String,
@Query("fromAddress") fromAddress: String,
@Query("from") fromAddress: String,
@Query("slippage") slippage: Int,
@Query("protocols") protocols: String? = null,
@Query("destReceiver") destinationAddress: String? = null,
@Query("referrerAddress") referrerAddress: String? = null,
@Query("receiver") destinationAddress: String? = null,
@Query("referrer") referrerAddress: String? = null,
@Query("fee") fee: String? = null,
@Query("disableEstimate") disableEstimate: Boolean? = null,
@Query("permit") permit: String? = null,
@Query("compatibilityMode") compatibilityMode: Boolean? = null,
@Query("compatibility") compatibilityMode: Boolean? = null,
@Query("burnChi") burnChi: Boolean? = null,
@Query("allowPartialFill") allowPartialFill: Boolean? = null,
@Query("parts") parts: String? = null,
@ -198,6 +199,7 @@ interface OneInchApi {
@Query("complexityLevel") complexityLevel: String? = null,
@Query("gasLimit") gasLimit: String? = null,
@Query("gasPrice") gasPrice: String? = null,
@Query("includeTokensInfo") includeTokensInfo: Boolean = true,
): Response<SwapResponse>
//endregion Swap
}

View file

@ -5,16 +5,10 @@ import com.squareup.moshi.Json
/**
* Quote response
*
* @property fromToken Source token info
* @property toToken Destination token info
* @property toTokenAmount Expected amount of destination token
* @property fromTokenAmount Amount of source token
* @property estimatedGas gas fee
*/
data class QuoteResponse(
@Json(name = "fromToken") val fromToken: TokenOneInchDto,
@Json(name = "toToken") val toToken: TokenOneInchDto,
@Json(name = "toTokenAmount") val toTokenAmount: String,
@Json(name = "fromTokenAmount") val fromTokenAmount: String,
@Json(name = "estimatedGas") val estimatedGas: Int,
@Json(name = "toAmount") val toTokenAmount: String,
)

View file

@ -5,7 +5,6 @@ import com.squareup.moshi.Json
data class SwapResponse(
@Json(name = "fromToken") val fromToken: TokenOneInchDto,
@Json(name = "toToken") val toToken: TokenOneInchDto,
@Json(name = "toTokenAmount") val toTokenAmount: String,
@Json(name = "fromTokenAmount") val fromTokenAmount: String,
@Json(name = "toAmount") val toTokenAmount: String,
@Json(name = "tx") val transaction: TransactionDto,
)

View file

@ -61,7 +61,7 @@ class OneInchApisModule {
}
companion object {
private const val ONE_INCH_BASE_URL = "https://api-tangem.1inch.io/v5.0/"
private const val ONE_INCH_BASE_URL = "https://api-tangem.1inch.io/v5.2/"
private const val ONE_INCH_ETH_PATH = "1/"
private const val ONE_INCH_BSC_PATH = "56/"
private const val ONE_INCH_POLYGON_PATH = "137/"

View file

@ -9,11 +9,7 @@ class QuotesConverter : Converter<QuoteResponse, QuoteModel> {
override fun convert(value: QuoteResponse): QuoteModel {
return QuoteModel(
fromTokenAmount = createFromAmountWithOffset(value.fromTokenAmount, value.fromToken.decimals),
toTokenAmount = createFromAmountWithOffset(value.toTokenAmount, value.toToken.decimals),
fromTokenAddress = value.fromToken.address,
toTokenAddress = value.toToken.address,
estimatedGas = value.estimatedGas,
)
}
}

View file

@ -11,9 +11,6 @@ class SwapConverter : Converter<SwapResponse, SwapDataModel> {
override fun convert(value: SwapResponse): SwapDataModel {
return SwapDataModel(
fromTokenAddress = value.fromToken.address,
toTokenAddress = value.toToken.address,
fromTokenAmount = createFromAmountWithOffset(value.fromTokenAmount, value.fromToken.decimals),
toTokenAmount = createFromAmountWithOffset(value.toTokenAmount, value.toToken.decimals),
transaction = convertTransaction(value.transaction),
)

View file

@ -99,6 +99,8 @@ interface SwapInteractor {
fun isAvailableToSwap(networkId: String): Boolean
fun getSwapAmountForToken(amount: String, token: Currency): SwapAmount
suspend fun checkFeeIsEnough(
fee: BigDecimal?,
spendAmount: SwapAmount,

View file

@ -215,11 +215,12 @@ internal class SwapInteractorImpl @Inject constructor(
amountToSwap: String,
fee: TxFee,
): TxState {
val amount = requireNotNull(toBigDecimalOrNull(amountToSwap)) { "wrong amount format, use only digits" }
val amountDecimal = requireNotNull(toBigDecimalOrNull(amountToSwap)) { "wrong amount format" }
val amount = SwapAmount(amountDecimal, getTokenDecimals(currencyToSend))
val result = transactionManager.sendTransaction(
txData = SwapTxData(
networkId = networkId,
amountToSend = amount,
amountToSend = amountDecimal,
currencyToSend = swapCurrencyConverter.convert(currencyToSend),
feeAmount = fee.feeValue,
gasLimit = fee.gasLimit,
@ -242,7 +243,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
TxState.TxSent(
fromAmount = amountFormatter.formatSwapAmountToUI(
swapStateData.swapModel.fromTokenAmount,
amount,
currencyToSend.symbol,
),
toAmount = amountFormatter.formatSwapAmountToUI(
@ -272,6 +273,11 @@ internal class SwapInteractorImpl @Inject constructor(
return ONE_INCH_SUPPORTED_NETWORKS.contains(networkId)
}
override fun getSwapAmountForToken(amount: String, token: Currency): SwapAmount {
val amountDecimal = requireNotNull(toBigDecimalOrNull(amount)) { "wrong amount format" }
return SwapAmount(amountDecimal, getTokenDecimals(token))
}
private suspend fun onSuccessLegacyFlow(currency: Currency) {
userWalletManager.addToken(swapCurrencyConverter.convert(currency), derivationPath)
userWalletManager.refreshWallet()
@ -412,7 +418,7 @@ internal class SwapInteractorImpl @Inject constructor(
networkId = networkId,
fromToken = fromToken,
toToken = toToken,
fromTokenAmount = quoteDataModel.fromTokenAmount,
fromTokenAmount = amount,
toTokenAmount = quoteDataModel.toTokenAmount,
swapStateData = null,
)
@ -494,7 +500,7 @@ internal class SwapInteractorImpl @Inject constructor(
networkId = networkId,
fromToken = fromToken,
toToken = toToken,
fromTokenAmount = swapData.fromTokenAmount,
fromTokenAmount = amount,
toTokenAmount = swapData.toTokenAmount,
swapStateData = SwapStateData(
fee = txFeeState,

View file

@ -5,16 +5,8 @@ import com.tangem.feature.swap.domain.models.SwapAmount
/**
* Quote model holds data about current amounts of exchange and fees
*
* @property fromTokenAmount amount of token you want to exchange
* @property toTokenAmount amount of token you want to receive
* @property fromTokenAddress address token you want to exchange
* @property toTokenAddress address token you want to receive
* @property estimatedGas fee
*/
data class QuoteModel(
val fromTokenAmount: SwapAmount,
val toTokenAmount: SwapAmount,
val fromTokenAddress: String,
val toTokenAddress: String,
val estimatedGas: Int,
)

View file

@ -5,15 +5,10 @@ import com.tangem.feature.swap.domain.models.SwapAmount
/**
* Swap transaction model
*
* @property fromTokenAddress token from which want to convert
* @property toTokenAddress token to want to convert
* @property toTokenAmount amount "target" token
* @property fromTokenAmount amount "initial" token
* @property transaction info about transaction
*/
data class SwapDataModel(
val fromTokenAddress: String,
val toTokenAddress: String,
val toTokenAmount: SwapAmount,
val fromTokenAmount: SwapAmount,
val transaction: TransactionModel,
)

View file

@ -482,8 +482,10 @@ internal class SwapViewModel @Inject constructor(
},
onSelectItemFee = { feeItem ->
dataState = dataState.copy(selectedFee = feeItem.data)
val spendAmount = dataState.swapDataModel?.swapModel?.fromTokenAmount
?: dataState.approveDataModel?.fromTokenAmount
val spendAmount = dataState.amount?.let { amount ->
val fromToken = dataState.fromCurrency ?: return@let null
swapInteractor.getSwapAmountForToken(amount, fromToken)
} ?: dataState.approveDataModel?.fromTokenAmount
spendAmount ?: return@UiActions
val fromToken = dataState.fromCurrency ?: return@UiActions
viewModelScope.launch(dispatchers.io) {