diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/ExpressApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/ExpressApi.kt deleted file mode 100644 index 0ed82c76d9..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/ExpressApi.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.tangem.datasource.api.express - -import com.tangem.datasource.api.common.response.ApiResponse -import com.tangem.datasource.api.express.models.request.AssetsRequestBody -import com.tangem.datasource.api.express.models.request.PairsRequestBody -import com.tangem.datasource.api.express.models.response.* -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.Query -import java.math.BigDecimal - -/** - * Interface of Tangem Express API (new swap mechanism) - */ -@Suppress("LongParameterList") -interface ExpressApi { - - @POST("assets") - suspend fun getAssets(@Body body: AssetsRequestBody): ApiResponse> - - @POST("pairs") - suspend fun getPairs(@Body body: PairsRequestBody): ApiResponse> - - @GET("providers") - suspend fun getProviders(): ApiResponse> - - @GET("exchange-quote") - suspend fun getExchangeQuote( - @Query("fromContractAddress") fromContractAddress: String, - @Query("fromNetwork") fromNetwork: String, - @Query("toContractAddress") toContractAddress: String, - @Query("toNetwork") toNetwork: String, - @Query("fromAmount") fromAmount: BigDecimal, - @Query("providerId") providerId: Int, - @Query("rateType") rateType: RateType, - ): ApiResponse - - @GET("exchange-data") - suspend fun getExchangeData( - @Query("fromContractAddress") fromContractAddress: String, - @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("toAddress") toAddress: String, - ): ApiResponse - - @GET("exchange-result") - suspend fun getExchangeResults(@Query("txId") txId: String): ApiResponse -} \ No newline at end of file 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 627e70bdd0..0c1fb16cf8 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 @@ -31,9 +31,9 @@ interface TangemExpressApi { @Query("fromNetwork") fromNetwork: String, @Query("toContractAddress") toContractAddress: String, @Query("toNetwork") toNetwork: String, - @Query("fromAmount") fromAmount: BigDecimal, + @Query("fromAmount") fromAmount: String, @Query("providerId") providerId: Int, - @Query("rateType") rateType: RateType, + @Query("rateType") rateType: String, ): ApiResponse @GET("exchange-data") diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeQuoteResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeQuoteResponse.kt index 214b4ac2d5..e643811822 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeQuoteResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeQuoteResponse.kt @@ -4,9 +4,23 @@ import com.squareup.moshi.Json import java.math.BigDecimal data class ExchangeQuoteResponse( + + @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 = "allowanceContract") val allowanceContract: String?, + + @Json(name = "minAmount") + val minAmount: BigDecimal, + ) \ 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 index 9aa4fc368b..0f8e561982 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 @@ -20,6 +20,7 @@ import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.swap.converters.* import com.tangem.feature.swap.domain.SwapRepository +import com.tangem.feature.swap.domain.models.createFromAmountWithOffset import com.tangem.feature.swap.domain.models.data.AggregatedSwapDataModel import com.tangem.feature.swap.domain.models.domain.* import com.tangem.feature.swap.domain.models.mapErrors @@ -127,21 +128,30 @@ internal class SwapRepositoryImpl @Inject constructor( } override suspend fun findBestQuote( - networkId: String, - fromTokenAddress: String, - toTokenAddress: String, - amount: String, + fromContractAddress: String, + fromNetwork: String, + toContractAddress: String, + toNetwork: String, + fromAmount: String, + providerId: Int, + rateType: RateType, ): AggregatedSwapDataModel { return withContext(coroutineDispatcher.io) { try { - val response = oneInchErrorsHandler.handleOneInchResponse( - getOneInchApi(networkId).quote( - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, - amount = amount, + val response = tangemExpressApi.getExchangeQuote( + fromContractAddress = fromContractAddress, + fromNetwork = fromNetwork, + toContractAddress = toContractAddress, + toNetwork = toNetwork, + fromAmount = fromAmount, + providerId = providerId, + rateType = rateType.name.lowercase(), + ).getOrThrow() + AggregatedSwapDataModel( + dataModel = QuoteModel( + toTokenAmount = createFromAmountWithOffset(response.toAmount, response.toDecimals), ), ) - AggregatedSwapDataModel(dataModel = quotesConverter.convert(response)) } catch (ex: OneIncResponseException) { AggregatedSwapDataModel(null, mapErrors(ex.data.description)) } @@ -263,7 +273,7 @@ internal class SwapRepositoryImpl @Inject constructor( fromNetwork: String, toContractAddress: String, toNetwork: String, - fromAmount: BigDecimal, + fromAmount: String, providerId: Int, rateType: RateType, ): ExchangeQuote { @@ -274,7 +284,7 @@ internal class SwapRepositoryImpl @Inject constructor( toNetwork, fromAmount, providerId, - rateTypeConverter.convertBack(rateType), + rateType.name.lowercase(), ).getOrThrow() return ExchangeQuote( 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 index 073c2464d8..c6ab0a7308 100644 --- 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 @@ -67,9 +67,10 @@ interface SwapInteractor { networkId: String, fromToken: CryptoCurrency, toToken: CryptoCurrency, + providers: List, amountToSwap: String, selectedFee: FeeType = FeeType.NORMAL, - ): SwapState + ): Map /** * Starts swap transaction, perform sign transaction 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 1cfcebfb20..dad225b375 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 @@ -13,6 +13,7 @@ import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.feature.swap.domain.cache.SwapDataCache import com.tangem.feature.swap.domain.converters.SwapCurrencyConverter import com.tangem.feature.swap.domain.models.SwapAmount +import com.tangem.feature.swap.domain.models.data.AggregatedSwapDataModel import com.tangem.feature.swap.domain.models.domain.* import com.tangem.feature.swap.domain.models.domain.Currency import com.tangem.feature.swap.domain.models.toStringWithRightOffset @@ -27,6 +28,9 @@ import timber.log.Timber import java.math.BigDecimal import java.math.RoundingMode import javax.inject.Inject +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope @Suppress("LargeClass", "LongParameterList") internal class SwapInteractorImpl @Inject constructor( @@ -274,13 +278,14 @@ internal class SwapInteractorImpl @Inject constructor( networkId: String, fromToken: CryptoCurrency, toToken: CryptoCurrency, + providers: List, amountToSwap: String, selectedFee: FeeType, - ): SwapState { + ): Map { syncWalletBalanceForTokens(networkId, listOf(fromToken, toToken)) val amountDecimal = toBigDecimalOrNull(amountToSwap) if (amountDecimal == null || amountDecimal.signum() == 0) { - return createEmptyAmountState(networkId, fromToken, toToken) + return providers.associateWith { createEmptyAmountState(networkId, fromToken, toToken) } } val amount = SwapAmount(amountDecimal, getTokenDecimals(fromToken)) val fromTokenAddress = getTokenAddress(fromToken) @@ -292,25 +297,27 @@ internal class SwapInteractorImpl @Inject constructor( } val isBalanceWithoutFeeEnough = isBalanceEnough(networkId, fromToken, amount, null) return if (isAllowedToSpend && isBalanceWithoutFeeEnough) { - loadSwapData( - networkId = networkId, - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, - fromToken = fromToken, - toToken = toToken, - amount = amount, - selectedFee = selectedFee, - ) + // TODO + providers.associateWith { + loadSwapData( + networkId = networkId, + fromTokenAddress = fromTokenAddress, + toTokenAddress = toTokenAddress, + fromToken = fromToken, + toToken = toToken, + amount = amount, + selectedFee = selectedFee, + ) + } } else { loadQuoteData( networkId = networkId, - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, amount = amount, fromToken = fromToken, toToken = toToken, isAllowedToSpend = isAllowedToSpend, isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, + providers = providers, ) } } @@ -513,45 +520,76 @@ internal class SwapInteractorImpl @Inject constructor( @Suppress("LongParameterList") private suspend fun loadQuoteData( networkId: String, - fromTokenAddress: String, - toTokenAddress: String, amount: SwapAmount, fromToken: CryptoCurrency, toToken: CryptoCurrency, + providers: List, + isAllowedToSpend: Boolean, + isBalanceWithoutFeeEnough: Boolean, + ): Map { + return coroutineScope { + val quoteRequests = providers.map { provider -> + async { + provider to repository.findBestQuote( + fromContractAddress = fromToken.getContractAddress(), + fromNetwork = fromToken.network.backendId, + toContractAddress = toToken.getContractAddress(), + toNetwork = toToken.network.backendId, + fromAmount = amount.toStringWithRightOffset(), + providerId = provider.providerId, + rateType = RateType.FLOAT, + ) + } + } + + quoteRequests.awaitAll().map { + it.first to + getState( + quoteDataModel = it.second, + amount = amount, + fromToken = fromToken, + toToken = toToken, + networkId = networkId, + isAllowedToSpend = isAllowedToSpend, + isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough + ) + }.associate { it.first to it.second } + } + } + + private suspend fun getState( + quoteDataModel: AggregatedSwapDataModel, + amount: SwapAmount, + fromToken: CryptoCurrency, + toToken: CryptoCurrency, + networkId: String, isAllowedToSpend: Boolean, isBalanceWithoutFeeEnough: Boolean, ): SwapState { - repository.findBestQuote( - networkId = networkId, - fromTokenAddress = fromTokenAddress, - toTokenAddress = toTokenAddress, - amount = amount.toStringWithRightOffset(), - ).let { quotes -> - val quoteDataModel = quotes.dataModel - if (quoteDataModel != null) { - val swapState = updateBalances( - networkId = networkId, - fromToken = fromToken, - toToken = toToken, - fromTokenAmount = amount, - toTokenAmount = quoteDataModel.toTokenAmount, - swapStateData = null, - ) - val quotesState = updatePermissionState( - networkId = networkId, - fromToken = fromToken, - swapAmount = amount, - quotesLoadedState = swapState, - ) - return quotesState.copy( - preparedSwapConfigState = quotesState.preparedSwapConfigState.copy( - isAllowedToSpend = isAllowedToSpend, - isBalanceEnough = isBalanceWithoutFeeEnough, - ), - ) - } else { - return SwapState.SwapError(quotes.error) - } + val quoteModel = quoteDataModel.dataModel + if (quoteModel != null) { + val swapState = updateBalances( + networkId = networkId, + fromToken = fromToken, + toToken = toToken, + fromTokenAmount = amount, + toTokenAmount = quoteModel.toTokenAmount, + swapStateData = null, + ) + val quotesState = updatePermissionState( + networkId = networkId, + fromToken = fromToken, + swapAmount = amount, + quotesLoadedState = swapState, + ) + return quotesState.copy( + preparedSwapConfigState = quotesState.preparedSwapConfigState.copy( + isAllowedToSpend = isAllowedToSpend, + isBalanceEnough = isBalanceWithoutFeeEnough, + ), + ) + } else { + return SwapState.SwapError(quoteDataModel.error) } } @@ -647,7 +685,10 @@ internal class SwapInteractorImpl @Inject constructor( ): SwapState.QuotesLoadedState { val appCurrency = userWalletManager.getUserAppCurrency() val nativeToken = userWalletManager.getNativeTokenForNetwork(networkId) - val rates = repository.getRates(appCurrency.code, listOf(fromToken.id.value, toToken.id.value, nativeToken.id)) + val rates = repository.getRates( + appCurrency.code, + listOf(fromToken.network.backendId, toToken.network.backendId, nativeToken.id), + ) val fromTokenBalance = cache.getBalanceForToken(networkId, derivationPath, fromToken.symbol) val toTokenBalance = cache.getBalanceForToken(networkId, derivationPath, toToken.symbol) return SwapState.QuotesLoadedState( @@ -657,7 +698,7 @@ internal class SwapInteractorImpl @Inject constructor( tokenWalletBalance = fromTokenBalance?.let { amountFormatter.formatSwapAmountToUI(it, "") } ?: ZERO_BALANCE, tokenFiatBalance = fromTokenAmount.value.toFiatString( - rateValue = rates[fromToken.id.value]?.toBigDecimal() ?: BigDecimal.ZERO, + rateValue = rates[fromToken.network.backendId]?.toBigDecimal() ?: BigDecimal.ZERO, fiatCurrencyName = appCurrency.symbol, formatWithSpaces = true, ), @@ -668,16 +709,16 @@ internal class SwapInteractorImpl @Inject constructor( tokenWalletBalance = toTokenBalance?.let { amountFormatter.formatSwapAmountToUI(it, "") } ?: ZERO_BALANCE, tokenFiatBalance = toTokenAmount.value.toFiatString( - rateValue = rates[toToken.id.value]?.toBigDecimal() ?: BigDecimal.ZERO, + rateValue = rates[toToken.network.backendId]?.toBigDecimal() ?: BigDecimal.ZERO, fiatCurrencyName = appCurrency.symbol, formatWithSpaces = true, ), ), priceImpact = calculatePriceImpact( fromTokenAmount = fromTokenAmount.value, - fromRate = rates[fromToken.id.value] ?: 0.0, + fromRate = rates[fromToken.network.backendId] ?: 0.0, toTokenAmount = toTokenAmount.value, - toRate = rates[toToken.id.value] ?: 0.0, + toRate = rates[toToken.network.backendId] ?: 0.0, ), networkCurrency = userWalletManager.getNetworkCurrency(networkId), swapDataModel = swapStateData, @@ -819,7 +860,7 @@ internal class SwapInteractorImpl @Inject constructor( private fun getTokenAddress(currency: CryptoCurrency): String { return when (currency) { is CryptoCurrency.Coin -> { - DEFAULT_BLOCKCHAIN_INCH_ADDRESS + "0" } is CryptoCurrency.Token -> { currency.contractAddress @@ -893,7 +934,6 @@ internal class SwapInteractorImpl @Inject constructor( companion object { private const val DEFAULT_SLIPPAGE = 2 private const val ZERO_BALANCE = "0" - private const val DEFAULT_BLOCKCHAIN_INCH_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" @Suppress("UnusedPrivateMember") private const val INCREASE_FEE_TO_CHECK_ENOUGH_PERCENT = 1.0 // if need to increase fee when check isEnough 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 d64b0fa8f0..4ba2f42f83 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 @@ -14,11 +14,15 @@ interface SwapRepository { suspend fun getExchangeableTokens(networkId: String): List + @Suppress("LongParameterList") suspend fun findBestQuote( - networkId: String, - fromTokenAddress: String, - toTokenAddress: String, - amount: String, + fromContractAddress: String, + fromNetwork: String, + toContractAddress: String, + toNetwork: String, + fromAmount: String, + providerId: Int, + rateType: RateType, ): AggregatedSwapDataModel /** @@ -68,7 +72,7 @@ interface SwapRepository { fromNetwork: String, toContractAddress: String, toNetwork: String, - fromAmount: BigDecimal, + fromAmount: String, providerId: Int, rateType: RateType, ): ExchangeQuote diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt index 8845c68949..56fd4124d3 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -1,6 +1,7 @@ package com.tangem.feature.swap.domain.di import com.tangem.domain.tokens.GetCardTokensListUseCase +import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeQuote.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeQuote.kt index ee352e70c4..41d7826e07 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeQuote.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeQuote.kt @@ -1,8 +1,6 @@ package com.tangem.feature.swap.domain.models.domain -import java.math.BigDecimal - data class ExchangeQuote( - val toAmount: BigDecimal, + val toAmount: String, val allowanceContract: String?, ) \ No newline at end of file diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 68b7f39e22..03199e51f5 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -18,6 +18,8 @@ import com.tangem.feature.swap.analytics.SwapEvents import com.tangem.feature.swap.domain.BlockchainInteractor import com.tangem.feature.swap.domain.SwapInteractor import com.tangem.feature.swap.domain.models.domain.PermissionOptions +import com.tangem.feature.swap.domain.models.domain.RateType +import com.tangem.feature.swap.domain.models.domain.SwapProvider import com.tangem.feature.swap.domain.models.formatToUIRepresentation import com.tangem.feature.swap.domain.models.ui.* import com.tangem.feature.swap.models.SwapPermissionState @@ -175,6 +177,7 @@ internal class SwapViewModel @Inject constructor( fromToken = fromCurrencyStatus.currency, toToken = selectedCurrency.currency, amount = lastAmount.value, + toProvidersList = findSwapProviders(fromCurrencyStatus, selectedCurrency) ) } } @@ -192,7 +195,12 @@ internal class SwapViewModel @Inject constructor( ) } - private fun startLoadingQuotes(fromToken: CryptoCurrency, toToken: CryptoCurrency, amount: String) { + private fun startLoadingQuotes( + fromToken: CryptoCurrency, + toToken: CryptoCurrency, + amount: String, + toProvidersList: List, + ) { singleTaskScheduler.cancelTask() uiState = stateBuilder.createQuotesLoadingState(uiState, fromToken, toToken, initialCryptoCurrency.id.value) singleTaskScheduler.scheduleTask( @@ -201,6 +209,7 @@ internal class SwapViewModel @Inject constructor( fromToken = fromToken, toToken = toToken, amount = amount, + toProvidersList = toProvidersList, ), ) } @@ -210,7 +219,12 @@ internal class SwapViewModel @Inject constructor( val toCurrency = dataState.toCryptoCurrency val amount = dataState.amount if (fromCurrency != null && toCurrency != null && amount != null) { - startLoadingQuotes(fromCurrency.currency, toCurrency.currency, amount) + startLoadingQuotes( + fromToken = fromCurrency.currency, + toToken = toCurrency.currency, + amount = amount, + toProvidersList = findSwapProviders(fromCurrency, toCurrency) + ) } } @@ -218,6 +232,7 @@ internal class SwapViewModel @Inject constructor( fromToken: CryptoCurrency, toToken: CryptoCurrency, amount: String, + toProvidersList: List, ): PeriodicTask { return PeriodicTask( UPDATE_DELAY, @@ -233,9 +248,10 @@ internal class SwapViewModel @Inject constructor( networkId = dataState.networkId, fromToken = fromToken, toToken = toToken, + providers = toProvidersList, amountToSwap = amount, selectedFee = dataState.selectedFee?.feeType ?: FeeType.NORMAL, - ) + ).entries.first().value// TODO } }, onSuccess = { swapState -> @@ -418,7 +434,12 @@ internal class SwapViewModel @Inject constructor( fromCryptoCurrency = fromToken, toCryptoCurrency = toToken, ) - startLoadingQuotes(fromToken.currency, toToken.currency, lastAmount.value) + startLoadingQuotes( + fromToken = fromToken.currency, + toToken = toToken.currency, + amount = lastAmount.value, + toProvidersList = findSwapProviders(fromToken, toToken) + ) swapRouter.openScreen(SwapNavScreen.Main) } } @@ -438,7 +459,12 @@ internal class SwapViewModel @Inject constructor( uiState, inputNumberFormatter.formatWithThousands(lastAmount.value, decimals), ) - startLoadingQuotes(newFromToken.currency, newToToken.currency, lastAmount.value) + startLoadingQuotes( + fromToken = newFromToken.currency, + toToken = newToToken.currency, + amount = lastAmount.value, + toProvidersList = findSwapProviders(newFromToken, newToToken) + ) } } @@ -452,7 +478,12 @@ internal class SwapViewModel @Inject constructor( uiState = stateBuilder.updateSwapAmount(uiState, inputNumberFormatter.formatWithThousands(cutValue, decimals)) amountDebouncer.debounce(viewModelScope, DEBOUNCE_AMOUNT_DELAY) { - startLoadingQuotes(fromToken.currency, toToken.currency, lastAmount.value) + startLoadingQuotes( + fromToken = fromToken.currency, + toToken = toToken.currency, + amount = lastAmount.value, + toProvidersList = findSwapProviders(fromToken, toToken) + ) } } } @@ -566,6 +597,22 @@ internal class SwapViewModel @Inject constructor( ) } + private fun findSwapProviders(fromToken: CryptoCurrencyStatus, toToken: CryptoCurrencyStatus): List { + val groupToFind = if (isOrderReversed) { + dataState.tokensDataState?.fromGroup + } else { + dataState.tokensDataState?.toGroup + } ?: return emptyList() + + val idToFind = if (isOrderReversed) { + fromToken.currency.id.value + } else { + toToken.currency.id.value + } + + return groupToFind.available.find { idToFind == it.currencyStatus.currency.id.value }?.providers ?: emptyList() + } + companion object { private const val loggingTag = "SwapViewModel" private const val INITIAL_AMOUNT = ""