Updated on 2026-08-14
This commit is contained in:
parent
78fab3a9de
commit
78f93a8491
18 changed files with 169 additions and 143 deletions
|
|
@ -1,8 +0,0 @@
|
|||
package com.tangem.datasource.api.oneinch
|
||||
|
||||
import com.tangem.datasource.api.oneinch.models.SwapErrorDto
|
||||
|
||||
data class BaseOneInchResponse<T>(
|
||||
val body: T?,
|
||||
val errorDto: SwapErrorDto?,
|
||||
)
|
||||
|
|
@ -58,7 +58,7 @@ interface OneInchApi {
|
|||
suspend fun approveAllowance(
|
||||
@Query("tokenAddress") tokenAddress: String,
|
||||
@Query("walletAddress") walletAddress: String,
|
||||
): AllowanceResponse
|
||||
): Response<AllowanceResponse>
|
||||
//endregion Approve
|
||||
|
||||
//region Info
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
package com.tangem.datasource.api.oneinch
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.api.oneinch.errors.OneIncResponseException
|
||||
import com.tangem.datasource.api.oneinch.models.SwapErrorDto
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class OneInchErrorsHandler @Inject constructor(private val moshi: Moshi) {
|
||||
class OneInchErrorsHandler @Inject constructor(moshi: Moshi) {
|
||||
|
||||
fun <T> handleOneInchResponse(response: Response<T>): BaseOneInchResponse<T> {
|
||||
val body = response.body()
|
||||
private val errorMoshiAdapter = moshi.adapter(SwapErrorDto::class.java)
|
||||
|
||||
@Throws(OneIncResponseException::class)
|
||||
fun <T> handleOneInchResponse(response: Response<T>): T {
|
||||
return if (response.isSuccessful) {
|
||||
return BaseOneInchResponse(body, null)
|
||||
response.body() ?: error("response body is null")
|
||||
} else {
|
||||
when (response.code()) {
|
||||
HTTP_CODE_400 -> {
|
||||
if (body != null) {
|
||||
BaseOneInchResponse(null, moshi.adapter(SwapErrorDto::class.java).fromJson(body.toString()))
|
||||
} else {
|
||||
throw HttpException(response)
|
||||
}
|
||||
val swapErrorDto = errorMoshiAdapter.fromJson(response.errorBody()?.string() ?: "")
|
||||
throw OneIncResponseException(swapErrorDto ?: throw HttpException(response))
|
||||
}
|
||||
else -> {
|
||||
throw HttpException(response)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.datasource.api.oneinch.errors
|
||||
|
||||
import com.tangem.datasource.api.oneinch.models.SwapErrorDto
|
||||
|
||||
class OneIncResponseException(val data: SwapErrorDto) : Exception()
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.swap
|
|||
|
||||
import com.tangem.datasource.api.oneinch.OneInchApi
|
||||
import com.tangem.datasource.api.oneinch.OneInchErrorsHandler
|
||||
import com.tangem.datasource.api.oneinch.errors.OneIncResponseException
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.feature.swap.converters.ApproveConverter
|
||||
import com.tangem.feature.swap.converters.QuotesConverter
|
||||
|
|
@ -11,8 +12,9 @@ import com.tangem.feature.swap.domain.SwapRepository
|
|||
import com.tangem.feature.swap.domain.models.AggregatedSwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.ApproveModel
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.mapErrors
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
|
@ -37,14 +39,18 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String):
|
||||
AggregatedSwapDataModel<QuoteModel> {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
val quoteResponse = oneInchErrorsHandler.handleOneInchResponse(
|
||||
oneInchApi.quote(
|
||||
fromTokenAddress = fromTokenAddress,
|
||||
toTokenAddress = toTokenAddress,
|
||||
amount = amount,
|
||||
),
|
||||
)
|
||||
quotesConverter.convert(quoteResponse)
|
||||
try {
|
||||
val response = oneInchErrorsHandler.handleOneInchResponse(
|
||||
oneInchApi.quote(
|
||||
fromTokenAddress = fromTokenAddress,
|
||||
toTokenAddress = toTokenAddress,
|
||||
amount = amount,
|
||||
),
|
||||
)
|
||||
AggregatedSwapDataModel(dataModel = quotesConverter.convert(response))
|
||||
} catch (ex: OneIncResponseException) {
|
||||
AggregatedSwapDataModel(null, mapErrors(ex.data.description))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,15 +60,23 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun dataToApprove(tokenAddress: String, amount: String): ApproveModel {
|
||||
override suspend fun dataToApprove(tokenAddress: String, amount: String?): ApproveModel {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
approveConverter.convert(oneInchApi.approveTransaction(tokenAddress, amount))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun checkTokensSpendAllowance(tokenAddress: String, walletAddress: String): String {
|
||||
override suspend fun checkTokensSpendAllowance(tokenAddress: String, walletAddress: String):
|
||||
AggregatedSwapDataModel<String> {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
oneInchApi.approveAllowance(tokenAddress, walletAddress).allowance
|
||||
try {
|
||||
val response = oneInchErrorsHandler.handleOneInchResponse(
|
||||
oneInchApi.approveAllowance(tokenAddress, walletAddress)
|
||||
)
|
||||
AggregatedSwapDataModel(response.allowance)
|
||||
} catch (ex: OneIncResponseException) {
|
||||
AggregatedSwapDataModel(null, mapErrors(ex.data.description))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,18 +88,20 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
slippage: Int,
|
||||
): AggregatedSwapDataModel<SwapDataModel> {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
val swapResponse = oneInchErrorsHandler.handleOneInchResponse(
|
||||
oneInchApi.swap(
|
||||
fromTokenAddress = fromTokenAddress,
|
||||
toTokenAddress = toTokenAddress,
|
||||
amount = amount,
|
||||
fromAddress = fromWalletAddress,
|
||||
slippage = slippage,
|
||||
),
|
||||
)
|
||||
swapConverter.convert(
|
||||
swapResponse,
|
||||
)
|
||||
try {
|
||||
val swapResponse = oneInchErrorsHandler.handleOneInchResponse(
|
||||
oneInchApi.swap(
|
||||
fromTokenAddress = fromTokenAddress,
|
||||
toTokenAddress = toTokenAddress,
|
||||
amount = amount,
|
||||
fromAddress = fromWalletAddress,
|
||||
slippage = slippage,
|
||||
),
|
||||
)
|
||||
AggregatedSwapDataModel(swapConverter.convert(swapResponse))
|
||||
} catch (ex: OneIncResponseException) {
|
||||
AggregatedSwapDataModel(null, mapErrors(ex.data.description))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,17 @@
|
|||
package com.tangem.feature.swap.converters
|
||||
|
||||
import com.tangem.datasource.api.oneinch.BaseOneInchResponse
|
||||
import com.tangem.datasource.api.oneinch.models.QuoteResponse
|
||||
import com.tangem.feature.swap.domain.models.AggregatedSwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.mapErrors
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
import javax.inject.Inject
|
||||
|
||||
class QuotesConverter @Inject constructor() : Converter<BaseOneInchResponse<QuoteResponse>, AggregatedSwapDataModel<QuoteModel>> {
|
||||
class QuotesConverter @Inject constructor() : Converter<QuoteResponse, QuoteModel> {
|
||||
|
||||
override fun convert(value: BaseOneInchResponse<QuoteResponse>): AggregatedSwapDataModel<QuoteModel> {
|
||||
val body = value.body
|
||||
return if (body != null) {
|
||||
AggregatedSwapDataModel(
|
||||
QuoteModel(
|
||||
fromTokenAmount = body.fromTokenAmount,
|
||||
toTokenAmount = body.toTokenAmount,
|
||||
estimatedGas = body.estimatedGas,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
AggregatedSwapDataModel(
|
||||
null,
|
||||
mapErrors(value.errorDto?.description),
|
||||
)
|
||||
}
|
||||
override fun convert(value: QuoteResponse): QuoteModel {
|
||||
return QuoteModel(
|
||||
fromTokenAmount = value.fromTokenAmount,
|
||||
toTokenAmount = value.toTokenAmount,
|
||||
estimatedGas = value.estimatedGas,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +1,22 @@
|
|||
package com.tangem.feature.swap.converters
|
||||
|
||||
import com.tangem.datasource.api.oneinch.BaseOneInchResponse
|
||||
import com.tangem.datasource.api.oneinch.models.SwapResponse
|
||||
import com.tangem.datasource.api.oneinch.models.TransactionDto
|
||||
import com.tangem.feature.swap.domain.models.AggregatedSwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.TransactionModel
|
||||
import com.tangem.feature.swap.domain.models.data.mapErrors
|
||||
import com.tangem.utils.converter.Converter
|
||||
import javax.inject.Inject
|
||||
|
||||
class SwapConverter @Inject constructor() : Converter<BaseOneInchResponse<SwapResponse>, AggregatedSwapDataModel<SwapDataModel>> {
|
||||
class SwapConverter @Inject constructor() : Converter<SwapResponse, SwapDataModel> {
|
||||
|
||||
override fun convert(value: BaseOneInchResponse<SwapResponse>): AggregatedSwapDataModel<SwapDataModel> {
|
||||
val body = value.body
|
||||
return if (body != null) {
|
||||
AggregatedSwapDataModel(
|
||||
SwapDataModel(
|
||||
fromTokenAddress = body.fromToken.address,
|
||||
toTokenAddress = body.toToken.address,
|
||||
toTokenAmount = body.fromTokenAmount,
|
||||
fromTokenAmount = body.toTokenAmount,
|
||||
transaction = convertTransaction(body.transaction),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
AggregatedSwapDataModel(
|
||||
null,
|
||||
mapErrors(value.errorDto?.description),
|
||||
)
|
||||
}
|
||||
override fun convert(value: SwapResponse): SwapDataModel {
|
||||
return SwapDataModel(
|
||||
fromTokenAddress = value.fromToken.address,
|
||||
toTokenAddress = value.toToken.address,
|
||||
toTokenAmount = value.fromTokenAmount,
|
||||
fromTokenAmount = value.toTokenAmount,
|
||||
transaction = convertTransaction(value.transaction),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertTransaction(transactionDto: TransactionDto): TransactionModel {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.feature.swap.domain.models.SwapResultModel
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState
|
||||
|
||||
interface SwapInteractor {
|
||||
|
||||
|
|
@ -10,11 +9,13 @@ interface SwapInteractor {
|
|||
|
||||
suspend fun getTokenBalance(tokenId: String): String
|
||||
|
||||
suspend fun givePermissionToSwap(tokenAddress: String)
|
||||
|
||||
suspend fun findBestQuote(
|
||||
fromTokenAddress: String,
|
||||
toTokenAddress: String,
|
||||
amount: String,
|
||||
): QuoteModel
|
||||
): SwapState
|
||||
|
||||
suspend fun onSwap(): SwapResultModel
|
||||
suspend fun onSwap(): SwapState
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.feature.swap.domain.cache.SwapDataCache
|
||||
import com.tangem.feature.swap.domain.models.SwapResultModel
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.DataError
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState
|
||||
import com.tangem.feature.swap.domain.models.data.TransactionModel
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import javax.inject.Inject
|
||||
|
|
@ -28,12 +28,20 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): QuoteModel {
|
||||
override suspend fun givePermissionToSwap(tokenAddress: String) {
|
||||
val oneInchAddress = repository.addressForTrust()
|
||||
val transactionData = repository.dataToApprove(tokenAddress)
|
||||
//todo sign transaction (next tasks)
|
||||
}
|
||||
|
||||
override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): SwapState {
|
||||
val networkId = cache.getNetworkId()
|
||||
val isAllowedToSpend = if (networkId.isNullOrEmpty()) {
|
||||
false
|
||||
} else {
|
||||
repository.checkTokensSpendAllowance(fromTokenAddress, userWalletManager.getWalletAddress(networkId)) != "0"
|
||||
val allowance =
|
||||
repository.checkTokensSpendAllowance(fromTokenAddress, userWalletManager.getWalletAddress(networkId))
|
||||
allowance.error == DataError.NO_ERROR && allowance.dataModel != "0"
|
||||
}
|
||||
repository.findBestQuote(fromTokenAddress, toTokenAddress, amount).let { quotes ->
|
||||
val quoteDataModel = quotes.dataModel
|
||||
|
|
@ -41,37 +49,37 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
cache.cacheSwapParams(quoteDataModel.copy(isAllowedToSpend = isAllowedToSpend), amount)
|
||||
return quoteDataModel
|
||||
} else {
|
||||
error("") //todo handle error in domain layer(task [REDACTED_TASK_KEY])
|
||||
return SwapState.SwapError(quotes.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onSwap(): SwapResultModel {
|
||||
override suspend fun onSwap(): SwapState {
|
||||
val quoteModel = cache.getLastQuote()
|
||||
val amountToSwap = cache.getAmountToSwap()
|
||||
val networkId = cache.getNetworkId()
|
||||
if (quoteModel != null && amountToSwap != null && networkId != null) {
|
||||
val swapData = repository.prepareSwapTransaction(
|
||||
repository.prepareSwapTransaction(
|
||||
fromTokenAddress = quoteModel.fromTokenAmount,
|
||||
toTokenAddress = quoteModel.toTokenAmount,
|
||||
amount = amountToSwap,
|
||||
slippage = DEFAULT_SLIPPAGE,
|
||||
fromWalletAddress = getWalletAddress(networkId),
|
||||
).dataModel
|
||||
if (swapData != null) {
|
||||
signTransactionData(swapData.transaction) //todo implement
|
||||
return SwapResultModel.SwapSuccess(
|
||||
quoteModel.fromTokenAmount,
|
||||
quoteModel.toTokenAmount,
|
||||
)
|
||||
} else {
|
||||
error("") //todo handle error in domain layer(task [REDACTED_TASK_KEY])
|
||||
).let {
|
||||
val swapData = it.dataModel
|
||||
if (swapData != null) {
|
||||
signTransactionData(swapData.transaction) //todo implement
|
||||
return SwapState.SwapSuccess(
|
||||
quoteModel.fromTokenAmount,
|
||||
quoteModel.toTokenAmount,
|
||||
)
|
||||
} else {
|
||||
return SwapState.SwapError(it.error)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw IllegalStateException("cache is empty, call 'findBestQuote' first")
|
||||
}
|
||||
return SwapResultModel.SwapError(
|
||||
0,
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
private fun getWalletAddress(networkId: String): String {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.feature.swap.domain
|
|||
import com.tangem.feature.swap.domain.models.AggregatedSwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.ApproveModel
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState
|
||||
|
||||
interface SwapRepository {
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ interface SwapRepository {
|
|||
fromTokenAddress: String,
|
||||
toTokenAddress: String,
|
||||
amount: String,
|
||||
): AggregatedSwapDataModel<QuoteModel>
|
||||
): AggregatedSwapDataModel<SwapState.QuoteModel>
|
||||
|
||||
/**
|
||||
* Returns address of 1inch router that must be trusted
|
||||
|
|
@ -31,7 +31,7 @@ interface SwapRepository {
|
|||
*/
|
||||
suspend fun dataToApprove(
|
||||
tokenAddress: String,
|
||||
amount: String,
|
||||
amount: String? = null,
|
||||
): ApproveModel
|
||||
|
||||
/**
|
||||
|
|
@ -42,7 +42,7 @@ interface SwapRepository {
|
|||
*
|
||||
* @return amount of tokens allowed to spend
|
||||
*/
|
||||
suspend fun checkTokensSpendAllowance(tokenAddress: String, walletAddress: String): String
|
||||
suspend fun checkTokensSpendAllowance(tokenAddress: String, walletAddress: String): AggregatedSwapDataModel<String>
|
||||
|
||||
suspend fun prepareSwapTransaction(
|
||||
fromTokenAddress: String,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.feature.swap.domain.cache
|
||||
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
|
||||
|
||||
interface SwapDataCache {
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.feature.swap.domain.cache
|
|||
|
||||
import com.tangem.feature.swap.domain.models.SwapDataHolder
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
|
||||
|
||||
class SwapDataCacheImpl : SwapDataCache {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
import com.tangem.feature.swap.domain.models.data.QuoteModel
|
||||
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
|
||||
|
||||
data class SwapDataHolder(
|
||||
val quoteModel: QuoteModel? = null,
|
||||
val quoteModel:
|
||||
QuoteModel? = null,
|
||||
val amountToSwap: String? = null,
|
||||
val networkId: String? = null,
|
||||
)
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
sealed interface SwapResultModel {
|
||||
|
||||
data class SwapSuccess(
|
||||
val fromTokenAmount: String,
|
||||
val toTokenAmount: String,
|
||||
) : SwapResultModel
|
||||
|
||||
data class SwapError(
|
||||
val errorCode: Int,
|
||||
val errorMessage: String,
|
||||
) : SwapResultModel
|
||||
}
|
||||
|
|
@ -3,16 +3,19 @@ package com.tangem.feature.swap.domain.models.data
|
|||
enum class DataError {
|
||||
NO_ERROR,
|
||||
UNKNOWN_ERROR,
|
||||
INSUFFICIENT_LIQUIDITY
|
||||
INSUFFICIENT_LIQUIDITY,
|
||||
CANNOT_SYNC
|
||||
}
|
||||
|
||||
fun mapErrors(error: String?): DataError {
|
||||
return if (error == null) {
|
||||
DataError.UNKNOWN_ERROR
|
||||
} else when (error) {
|
||||
INSUFFICIENT_LIQUIDITY_ERROR -> DataError.INSUFFICIENT_LIQUIDITY
|
||||
} else when {
|
||||
error == INSUFFICIENT_LIQUIDITY_ERROR -> DataError.INSUFFICIENT_LIQUIDITY
|
||||
error.startsWith(CANNOT_SYNC_ERROR) -> DataError.CANNOT_SYNC
|
||||
else -> DataError.UNKNOWN_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
private const val INSUFFICIENT_LIQUIDITY_ERROR = "insufficient liquidity"
|
||||
private const val INSUFFICIENT_LIQUIDITY_ERROR = "insufficient liquidity"
|
||||
private const val CANNOT_SYNC_ERROR = "cannot sync"
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
|
||||
data class QuoteModel(
|
||||
val fromTokenAmount: String,
|
||||
val toTokenAmount: String,
|
||||
val estimatedGas: Int,
|
||||
val isAllowedToSpend: Boolean = false,
|
||||
)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
|
||||
sealed interface SwapState {
|
||||
|
||||
data class QuoteModel(
|
||||
val fromTokenAmount: String,
|
||||
val toTokenAmount: String,
|
||||
val estimatedGas: Int,
|
||||
val isAllowedToSpend: Boolean = false,
|
||||
) : SwapState
|
||||
|
||||
data class SwapSuccess(
|
||||
val fromTokenAmount: String,
|
||||
val toTokenAmount: String,
|
||||
) : SwapState
|
||||
|
||||
data class SwapError(
|
||||
val errorType: DataError,
|
||||
) : SwapState
|
||||
}
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
package com.tangem.feature.swap.viewmodels
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.feature.swap.domain.models.data.Currency
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -12,4 +16,28 @@ internal class SwapViewModel @Inject constructor(
|
|||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : ViewModel() {
|
||||
|
||||
// region temp for test
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
runCatching {
|
||||
val tokens = referralInteractor.getTokensToSwap("binance-smart-chain")
|
||||
val token = tokens[1]
|
||||
val token2 = tokens[2]
|
||||
if (token is Currency.NonNativeToken && token2 is Currency.NonNativeToken) {
|
||||
findBestQuotes(token.contractAddress, token2.contractAddress)
|
||||
}
|
||||
}.onFailure {
|
||||
Log.e("SwapViewModel", it.message ?: it.cause.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun findBestQuotes(fromTokenAddress: String, toTokenAddress: String) {
|
||||
referralInteractor.findBestQuote(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
"1",
|
||||
)
|
||||
}
|
||||
// endregion temp for test
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue