Updated on 2026-08-14
This commit is contained in:
parent
479d554dae
commit
75075b53c8
18 changed files with 412 additions and 229 deletions
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.operations.TokenListOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
class GetCryptoCurrencyStatusUseCase(
|
||||
internal val currenciesRepository: CurrenciesRepository,
|
||||
internal val quotesRepository: QuotesRepository,
|
||||
internal val networksRepository: NetworksRepository,
|
||||
internal val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<Either<TokenListError, List<CryptoCurrencyStatus>>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
userWalletId = userWalletId,
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
)
|
||||
|
||||
return operations.getCurrenciesStatusesFlow()
|
||||
.map { maybeCurrenciesStatuses ->
|
||||
maybeCurrenciesStatuses.mapLeft(CurrenciesStatusesOperations.Error::mapToTokenListError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTokenList(
|
||||
userWalletId: UserWalletId,
|
||||
tokens: List<CryptoCurrencyStatus>,
|
||||
): Flow<Either<TokenListError, TokenList>> {
|
||||
val operations = TokenListOperations(
|
||||
userWalletId = userWalletId,
|
||||
tokens = tokens,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
|
||||
return operations.getTokenListFlow().map { maybeTokenList ->
|
||||
maybeTokenList.mapLeft(TokenListOperations.Error::mapToTokenListError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -193,26 +193,26 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
|
||||
override suspend fun getCryptoCurrency(
|
||||
userWallet: UserWallet,
|
||||
currency: Currency,
|
||||
currency: CryptoCurrency,
|
||||
network: Network,
|
||||
): CryptoCurrency? {
|
||||
val blockchain = Blockchain.fromNetworkId(currency.networkId) ?: return null
|
||||
val blockchain = Blockchain.fromNetworkId(currency.network.id.value) ?: return null
|
||||
val cryptoCurrencyFactory = CryptoCurrencyFactory()
|
||||
return when (currency) {
|
||||
is Currency.NativeToken -> {
|
||||
is CryptoCurrency.Coin -> {
|
||||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = network.derivationPath.value,
|
||||
derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider,
|
||||
)
|
||||
}
|
||||
is Currency.NonNativeToken -> {
|
||||
is CryptoCurrency.Token -> {
|
||||
val sdkToken = SdkToken(
|
||||
name = currency.name,
|
||||
symbol = currency.symbol,
|
||||
contractAddress = currency.contractAddress,
|
||||
decimals = currency.decimalCount,
|
||||
id = currency.id,
|
||||
decimals = currency.decimals,
|
||||
id = currency.id.value,
|
||||
)
|
||||
cryptoCurrencyFactory.createToken(
|
||||
sdkToken = sdkToken,
|
||||
|
|
@ -258,7 +258,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
userWalletId: UserWalletId,
|
||||
networkId: String,
|
||||
derivationPath: String?,
|
||||
currency: Currency,
|
||||
currency: CryptoCurrency,
|
||||
amount: BigDecimal?,
|
||||
): String {
|
||||
val blockchain =
|
||||
|
|
@ -276,16 +276,16 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
) ?: error("Cannot cast to Approver")
|
||||
}
|
||||
|
||||
private fun convertToAmount(amount: BigDecimal, currency: Currency, blockchain: Blockchain): Amount {
|
||||
private fun convertToAmount(amount: BigDecimal, currency: CryptoCurrency, blockchain: Blockchain): Amount {
|
||||
return when (currency) {
|
||||
is Currency.NativeToken -> {
|
||||
is CryptoCurrency.Token -> {
|
||||
Amount(value = amount, blockchain = blockchain)
|
||||
}
|
||||
is Currency.NonNativeToken -> {
|
||||
is CryptoCurrency.Coin -> {
|
||||
Amount(
|
||||
currencySymbol = currency.symbol,
|
||||
value = amount,
|
||||
decimals = currency.decimalCount,
|
||||
decimals = currency.decimals,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.NetworkInfo
|
||||
|
||||
interface BlockchainInteractor {
|
||||
|
||||
fun getTokenDecimals(token: Currency): Int
|
||||
fun getTokenDecimals(token: CryptoCurrency): Int
|
||||
|
||||
/**
|
||||
* In app blockchain id, actual in blockchain sdk, not the same as networkId
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.NetworkInfo
|
||||
import com.tangem.lib.crypto.TransactionManager
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class BlockchainInteractorImpl @Inject constructor(
|
||||
internal class DefaultBlockchainInteractor @Inject constructor(
|
||||
private val transactionManager: TransactionManager,
|
||||
) : BlockchainInteractor {
|
||||
|
||||
|
|
@ -23,11 +23,11 @@ internal class BlockchainInteractorImpl @Inject constructor(
|
|||
return transactionManager.getExplorerTransactionLink(networkId, txAddress)
|
||||
}
|
||||
|
||||
override fun getTokenDecimals(token: Currency): Int {
|
||||
return if (token is Currency.NonNativeToken) {
|
||||
token.decimalCount
|
||||
override fun getTokenDecimals(token: CryptoCurrency): Int {
|
||||
return if (token is CryptoCurrency.Token) {
|
||||
token.decimals
|
||||
} else {
|
||||
transactionManager.getNativeTokenDecimals(token.networkId)
|
||||
transactionManager.getNativeTokenDecimals(token.network.id.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,9 +9,7 @@ import java.math.BigDecimal
|
|||
|
||||
interface SwapInteractor {
|
||||
|
||||
suspend fun getPairs(currency: Currency): List<SwapPair>
|
||||
|
||||
suspend fun getPairs(initialCurrency: LeastTokenInfo, currenciesList: List<CryptoCurrency>): List<SwapPairLeast>
|
||||
suspend fun getTokensDataState(currency: Currency): TokensDataStateExpress
|
||||
|
||||
fun initDerivationPathAndNetwork(derivationPath: String?, network: Network?)
|
||||
|
||||
|
|
@ -31,17 +29,17 @@ interface SwapInteractor {
|
|||
*
|
||||
* @param networkId networkId for tokens
|
||||
* @param searchQuery string query for search
|
||||
* @return [FoundTokensState] that contains list of tokens matching condition query
|
||||
* @return [FoundTokensStateExpress] that contains list of tokens matching condition query
|
||||
*/
|
||||
suspend fun searchTokens(networkId: String, searchQuery: String): FoundTokensState
|
||||
suspend fun searchTokens(networkId: String, searchQuery: String): FoundTokensStateExpress
|
||||
|
||||
/**
|
||||
* Find specific token by id, null if not found
|
||||
*
|
||||
* @param id token id
|
||||
* @return [Currency] or null
|
||||
* @return [CryptoCurrency] or null
|
||||
*/
|
||||
fun findTokenById(id: String): Currency?
|
||||
fun findTokenById(id: String): CryptoCurrency?
|
||||
|
||||
/**
|
||||
* Gives permission to swap, this starts scan card process
|
||||
|
|
@ -66,8 +64,8 @@ interface SwapInteractor {
|
|||
@Throws(IllegalStateException::class)
|
||||
suspend fun findBestQuote(
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
amountToSwap: String,
|
||||
selectedFee: FeeType = FeeType.NORMAL,
|
||||
): SwapState
|
||||
|
|
@ -88,8 +86,8 @@ interface SwapInteractor {
|
|||
suspend fun onSwap(
|
||||
networkId: String,
|
||||
swapStateData: SwapStateData,
|
||||
currencyToSend: Currency,
|
||||
currencyToGet: Currency,
|
||||
currencyToSend: CryptoCurrency,
|
||||
currencyToGet: CryptoCurrency,
|
||||
amountToSwap: String,
|
||||
fee: TxFee,
|
||||
): TxState
|
||||
|
|
@ -100,16 +98,16 @@ interface SwapInteractor {
|
|||
* @param networkId
|
||||
* @param token
|
||||
*/
|
||||
fun getTokenBalance(networkId: String, token: Currency): SwapAmount
|
||||
fun getTokenBalance(networkId: String, token: CryptoCurrency): SwapAmount
|
||||
|
||||
fun isAvailableToSwap(networkId: String): Boolean
|
||||
|
||||
fun getSwapAmountForToken(amount: String, token: Currency): SwapAmount
|
||||
fun getSwapAmountForToken(amount: String, token: CryptoCurrency): SwapAmount
|
||||
|
||||
suspend fun checkFeeIsEnough(
|
||||
fee: BigDecimal?,
|
||||
spendAmount: SwapAmount,
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
): Boolean
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.feature.swap.domain.cache.SwapDataCache
|
||||
import com.tangem.feature.swap.domain.converters.SwapCurrencyConverter
|
||||
|
|
@ -21,6 +22,7 @@ import com.tangem.lib.crypto.UserWalletManager
|
|||
import com.tangem.lib.crypto.models.*
|
||||
import com.tangem.lib.crypto.models.transactions.SendTxResult
|
||||
import com.tangem.utils.toFiatString
|
||||
import kotlinx.coroutines.flow.first
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
|
@ -37,7 +39,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
private val networksRepository: NetworksRepository,
|
||||
private val walletFeatureToggles: WalletFeatureToggles,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusUseCase,
|
||||
) : SwapInteractor {
|
||||
|
||||
// TODO: Move to DI
|
||||
|
|
@ -50,26 +52,65 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
private var derivationPath: String? = null
|
||||
private var network: Network? = null
|
||||
|
||||
override suspend fun getPairs(currency: Currency): List<SwapPair> {
|
||||
val currencies = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { selectedWallet ->
|
||||
getCryptoCurrenciesUseCase(selectedWallet.walletId).fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { it },
|
||||
)
|
||||
},
|
||||
override suspend fun getTokensDataState(currency: Currency): TokensDataStateExpress {
|
||||
val selectedWallet = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { null },
|
||||
ifRight = { it },
|
||||
)
|
||||
|
||||
val pairs = getPairs(
|
||||
requireNotNull(selectedWallet)
|
||||
|
||||
val currencyStatuses = getMultiCryptoCurrencyStatusUseCase(selectedWallet.walletId)
|
||||
.first()
|
||||
.getOrElse { emptyList() }
|
||||
// .filter { it.currency.network.backendId != currency.networkId }
|
||||
val currencies = currencyStatuses.map { it.currency }
|
||||
|
||||
val pairsLeast = getPairs(
|
||||
initialCurrency = LeastTokenInfo(
|
||||
contractAddress = (currency as? Currency.NonNativeToken)?.contractAddress ?: "0",
|
||||
network = currency.networkId,
|
||||
),
|
||||
currenciesList = currencies,
|
||||
currenciesList = currencyStatuses.map { it.currency },
|
||||
)
|
||||
|
||||
return createCryptoCurrencyPairs(pairs, currencies)
|
||||
val pairs = createCryptoCurrencyPairs(pairsLeast, currencies)
|
||||
|
||||
val initialCryptoCurrency = mapLegacyCurrencyToCryptoCurrency(currency, currencyStatuses)
|
||||
?: error("Initial crypto currency must not be null")
|
||||
|
||||
return TokensDataStateExpress(
|
||||
initialCryptoCurrency = initialCryptoCurrency,
|
||||
preselectTokens = getPreselectTokens(currency, currencyStatuses),
|
||||
foundTokensState = FoundTokensStateExpress(emptyList(), emptyList()),
|
||||
pairs = pairs,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getPreselectTokens(currency: Currency, currencies: List<CryptoCurrencyStatus>): PreselectTokensExpress {
|
||||
val from = mapLegacyCurrencyToCryptoCurrency(currency, currencies)
|
||||
|
||||
val to = currencies.firstOrNull()?.currency // TODO choose of 3 variants
|
||||
|
||||
if (from != null && to != null) {
|
||||
return PreselectTokensExpress(
|
||||
fromToken = from,
|
||||
toToken = to,
|
||||
)
|
||||
} else {
|
||||
error("From and to currencies must not be null")
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapLegacyCurrencyToCryptoCurrency(
|
||||
currency: Currency,
|
||||
currencies: List<CryptoCurrencyStatus>,
|
||||
): CryptoCurrency? {
|
||||
return currencies.map { it.currency }
|
||||
.find {
|
||||
it.network.backendId == currency.networkId &&
|
||||
it.getContractAddress() == currency.getContractAddress()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCryptoCurrencyPairs(
|
||||
|
|
@ -97,22 +138,35 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
): CryptoCurrency? {
|
||||
return cryptoCurrenciesList.find {
|
||||
it.network.backendId == leastTokenInfo.network &&
|
||||
(it as? CryptoCurrency.Token)?.contractAddress ?: "0" == leastTokenInfo.contractAddress
|
||||
it.getContractAddress() == leastTokenInfo.contractAddress
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPairs(
|
||||
initialCurrency: LeastTokenInfo,
|
||||
currenciesList: List<CryptoCurrency>,
|
||||
): List<SwapPairLeast> {
|
||||
private fun CryptoCurrency.getContractAddress(): String {
|
||||
return when (this) {
|
||||
is CryptoCurrency.Token -> this.contractAddress
|
||||
is CryptoCurrency.Coin -> "0"
|
||||
}
|
||||
}
|
||||
|
||||
private fun Currency.getContractAddress(): String {
|
||||
return when (this) {
|
||||
is Currency.NativeToken -> "0"
|
||||
is Currency.NonNativeToken -> this.contractAddress
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getPairs(initialCurrency: LeastTokenInfo, currenciesList: List<CryptoCurrency>): List<SwapPairLeast> {
|
||||
return repository.getPairs(initialCurrency, currenciesList)
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override fun initDerivationPathAndNetwork(derivationPath: String?, network: Network?) {
|
||||
this.derivationPath = derivationPath
|
||||
this.network = network
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override suspend fun initTokensToSwap(initialCurrency: Currency): TokensDataState {
|
||||
// TODO: refactor this function
|
||||
val networkId = initialCurrency.networkId
|
||||
|
|
@ -134,7 +188,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
allLoadedTokens.firstOrNull { it.symbol == token.symbol }?.let {
|
||||
loadedOnWalletsMap.add(it.symbol)
|
||||
it
|
||||
} ?: swapCurrencyConverter.convertBack(token)
|
||||
} ?: TODO()
|
||||
}
|
||||
.filter { it.symbol != initialCurrency.symbol && allLoadedTokens.contains(it) }
|
||||
val loadedTokens = allLoadedTokens
|
||||
|
|
@ -146,21 +200,22 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
val appCurrency = userWalletManager.getUserAppCurrency()
|
||||
val rates = repository.getRates(appCurrency.code, tokensInWallet.map { it.id })
|
||||
cache.cacheBalances(networkId, derivationPath, tokensBalance)
|
||||
cache.cacheLoadedTokens(loadedTokens.map { TokenWithBalance(it) })
|
||||
cache.cacheInWalletTokens(getTokensWithBalance(tokensInWallet, tokensBalance, rates, appCurrency))
|
||||
// cache.cacheLoadedTokens(loadedTokens.map { TokenWithBalance(it) })
|
||||
// cache.cacheInWalletTokens(getTokensWithBalance(tokensInWallet, tokensBalance, rates, appCurrency))
|
||||
return TokensDataState(
|
||||
preselectTokens = PreselectTokens(
|
||||
fromToken = initialCurrency,
|
||||
toToken = selectToToken(initialCurrency, tokensInWallet, loadedTokens),
|
||||
),
|
||||
foundTokensState = FoundTokensState(
|
||||
tokensInWallet = cache.getInWalletTokens(),
|
||||
loadedTokens = cache.getLoadedTokens(),
|
||||
tokensInWallet = emptyList(), // cache.getInWalletTokens(),
|
||||
loadedTokens = emptyList(), // cache.getLoadedTokens(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun searchTokens(networkId: String, searchQuery: String): FoundTokensState {
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override suspend fun searchTokens(networkId: String, searchQuery: String): FoundTokensStateExpress {
|
||||
val searchQueryLowerCase = searchQuery.lowercase()
|
||||
val tokensInWallet = cache.getInWalletTokens()
|
||||
.filter {
|
||||
|
|
@ -172,19 +227,21 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
it.token.name.lowercase().contains(searchQueryLowerCase) ||
|
||||
it.token.symbol.lowercase().contains(searchQueryLowerCase)
|
||||
}
|
||||
return FoundTokensState(
|
||||
return FoundTokensStateExpress(
|
||||
tokensInWallet = tokensInWallet,
|
||||
loadedTokens = loadedTokens,
|
||||
)
|
||||
}
|
||||
|
||||
override fun findTokenById(id: String): Currency? {
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override fun findTokenById(id: String): CryptoCurrency? {
|
||||
val tokensInWallet = cache.getInWalletTokens()
|
||||
val loadedTokens = cache.getLoadedTokens()
|
||||
return tokensInWallet.firstOrNull { it.token.id == id }?.token
|
||||
?: loadedTokens.firstOrNull { it.token.id == id }?.token
|
||||
return tokensInWallet.firstOrNull { it.token.id.value == id }?.token
|
||||
?: loadedTokens.firstOrNull { it.token.id.value == id }?.token
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override suspend fun givePermissionToSwap(networkId: String, permissionOptions: PermissionOptions): TxState {
|
||||
val dataToSign = if (permissionOptions.approveType == SwapApproveType.UNLIMITED) {
|
||||
getApproveData(
|
||||
|
|
@ -223,10 +280,11 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override suspend fun findBestQuote(
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
amountToSwap: String,
|
||||
selectedFee: FeeType,
|
||||
): SwapState {
|
||||
|
|
@ -268,11 +326,12 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override suspend fun onSwap(
|
||||
networkId: String,
|
||||
swapStateData: SwapStateData,
|
||||
currencyToSend: Currency,
|
||||
currencyToGet: Currency,
|
||||
currencyToSend: CryptoCurrency,
|
||||
currencyToGet: CryptoCurrency,
|
||||
amountToSwap: String,
|
||||
fee: TxFee,
|
||||
): TxState {
|
||||
|
|
@ -322,7 +381,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getTokenBalance(networkId: String, token: Currency): SwapAmount {
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override fun getTokenBalance(networkId: String, token: CryptoCurrency): SwapAmount {
|
||||
return cache.getBalanceForToken(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
|
|
@ -330,25 +390,28 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
) ?: SwapAmount(BigDecimal.ZERO, getTokenDecimals(token))
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override fun isAvailableToSwap(networkId: String): Boolean {
|
||||
return ONE_INCH_SUPPORTED_NETWORKS.contains(networkId)
|
||||
}
|
||||
|
||||
override fun getSwapAmountForToken(amount: String, token: Currency): SwapAmount {
|
||||
@Deprecated("used in old swap mechanism")
|
||||
override fun getSwapAmountForToken(amount: String, token: CryptoCurrency): SwapAmount {
|
||||
val amountDecimal = requireNotNull(toBigDecimalOrNull(amount)) { "wrong amount format" }
|
||||
return SwapAmount(amountDecimal, getTokenDecimals(token))
|
||||
}
|
||||
|
||||
private suspend fun onSuccessLegacyFlow(currency: Currency) {
|
||||
@Deprecated("used in old swap mechanism")
|
||||
private suspend fun onSuccessLegacyFlow(currency: CryptoCurrency) {
|
||||
userWalletManager.addToken(swapCurrencyConverter.convert(currency), derivationPath)
|
||||
userWalletManager.refreshWallet()
|
||||
}
|
||||
|
||||
private suspend fun onSuccessNewFlow(currency: Currency) {
|
||||
val network = network ?: return
|
||||
@Deprecated("used in old swap mechanism")
|
||||
private suspend fun onSuccessNewFlow(currency: CryptoCurrency) {
|
||||
getSelectedWalletSyncUseCase().fold(
|
||||
ifRight = { userWallet ->
|
||||
getAndAddCryptoCurrency(userWallet, currency, network)
|
||||
addCryptoCurrenciesUseCase(userWallet.walletId, currency)
|
||||
},
|
||||
ifLeft = {
|
||||
Timber.e("Swap Error on getSelectedWalletUseCase")
|
||||
|
|
@ -356,24 +419,20 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun getAndAddCryptoCurrency(userWallet: UserWallet, currency: Currency, network: Network) {
|
||||
repository.getCryptoCurrency(userWallet, currency, network)?.let { cryptoCurrency ->
|
||||
addCryptoCurrenciesUseCase(userWallet.walletId, cryptoCurrency)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
private fun getTangemFee(): Double {
|
||||
return repository.getTangemFee()
|
||||
}
|
||||
|
||||
private fun getTokenDecimals(token: Currency): Int {
|
||||
return if (token is Currency.NonNativeToken) {
|
||||
token.decimalCount
|
||||
private fun getTokenDecimals(token: CryptoCurrency): Int {
|
||||
return if (token is CryptoCurrency.Token) {
|
||||
token.decimals
|
||||
} else {
|
||||
transactionManager.getNativeTokenDecimals(token.networkId)
|
||||
transactionManager.getNativeTokenDecimals(token.network.id.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
private fun selectToToken(
|
||||
initialToken: Currency,
|
||||
tokensInWallet: List<Currency>,
|
||||
|
|
@ -394,6 +453,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
return toToken
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
private fun getTokensWithBalance(
|
||||
tokens: List<Currency>,
|
||||
balances: Map<String, SwapAmount>,
|
||||
|
|
@ -418,8 +478,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun isAllowedToSpend(networkId: String, fromToken: Currency, amount: SwapAmount): Boolean {
|
||||
if (fromToken is Currency.NativeToken) return true
|
||||
private suspend fun isAllowedToSpend(networkId: String, fromToken: CryptoCurrency, amount: SwapAmount): Boolean {
|
||||
if (fromToken is CryptoCurrency.Coin) return true
|
||||
return getSelectedWalletSyncUseCase().fold(
|
||||
ifRight = { userWallet ->
|
||||
val allowance = repository.getAllowance(
|
||||
|
|
@ -438,7 +498,11 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createEmptyAmountState(networkId: String, fromToken: Currency, toToken: Currency): SwapState {
|
||||
private fun createEmptyAmountState(
|
||||
networkId: String,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
): SwapState {
|
||||
val appCurrency = userWalletManager.getUserAppCurrency()
|
||||
val fromTokenBalance = cache.getBalanceForToken(networkId, derivationPath, fromToken.symbol)
|
||||
val toTokenBalance = cache.getBalanceForToken(networkId, derivationPath, toToken.symbol)
|
||||
|
|
@ -462,8 +526,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
fromTokenAddress: String,
|
||||
toTokenAddress: String,
|
||||
amount: SwapAmount,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
isAllowedToSpend: Boolean,
|
||||
isBalanceWithoutFeeEnough: Boolean,
|
||||
): SwapState {
|
||||
|
|
@ -520,8 +584,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
networkId: String,
|
||||
fromTokenAddress: String,
|
||||
toTokenAddress: String,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
amount: SwapAmount,
|
||||
selectedFee: FeeType,
|
||||
): SwapState {
|
||||
|
|
@ -585,45 +649,45 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
@Suppress("LongParameterList")
|
||||
private suspend fun updateBalances(
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
fromTokenAmount: SwapAmount,
|
||||
toTokenAmount: SwapAmount,
|
||||
swapStateData: SwapStateData?,
|
||||
): SwapState.QuotesLoadedState {
|
||||
val appCurrency = userWalletManager.getUserAppCurrency()
|
||||
val nativeToken = userWalletManager.getNativeTokenForNetwork(networkId)
|
||||
val rates = repository.getRates(appCurrency.code, listOf(fromToken.id, toToken.id, nativeToken.id))
|
||||
val rates = repository.getRates(appCurrency.code, listOf(fromToken.id.value, toToken.id.value, nativeToken.id))
|
||||
val fromTokenBalance = cache.getBalanceForToken(networkId, derivationPath, fromToken.symbol)
|
||||
val toTokenBalance = cache.getBalanceForToken(networkId, derivationPath, toToken.symbol)
|
||||
return SwapState.QuotesLoadedState(
|
||||
fromTokenInfo = TokenSwapInfo(
|
||||
tokenAmount = fromTokenAmount,
|
||||
coinId = fromToken.id,
|
||||
coinId = fromToken.id.value,
|
||||
tokenWalletBalance = fromTokenBalance?.let { amountFormatter.formatSwapAmountToUI(it, "") }
|
||||
?: ZERO_BALANCE,
|
||||
tokenFiatBalance = fromTokenAmount.value.toFiatString(
|
||||
rateValue = rates[fromToken.id]?.toBigDecimal() ?: BigDecimal.ZERO,
|
||||
rateValue = rates[fromToken.id.value]?.toBigDecimal() ?: BigDecimal.ZERO,
|
||||
fiatCurrencyName = appCurrency.symbol,
|
||||
formatWithSpaces = true,
|
||||
),
|
||||
),
|
||||
toTokenInfo = TokenSwapInfo(
|
||||
tokenAmount = toTokenAmount,
|
||||
coinId = toToken.id,
|
||||
coinId = toToken.id.value,
|
||||
tokenWalletBalance = toTokenBalance?.let { amountFormatter.formatSwapAmountToUI(it, "") }
|
||||
?: ZERO_BALANCE,
|
||||
tokenFiatBalance = toTokenAmount.value.toFiatString(
|
||||
rateValue = rates[toToken.id]?.toBigDecimal() ?: BigDecimal.ZERO,
|
||||
rateValue = rates[toToken.id.value]?.toBigDecimal() ?: BigDecimal.ZERO,
|
||||
fiatCurrencyName = appCurrency.symbol,
|
||||
formatWithSpaces = true,
|
||||
),
|
||||
),
|
||||
priceImpact = calculatePriceImpact(
|
||||
fromTokenAmount = fromTokenAmount.value,
|
||||
fromRate = rates[fromToken.id] ?: 0.0,
|
||||
fromRate = rates[fromToken.id.value] ?: 0.0,
|
||||
toTokenAmount = toTokenAmount.value,
|
||||
toRate = rates[toToken.id] ?: 0.0,
|
||||
toRate = rates[toToken.id.value] ?: 0.0,
|
||||
),
|
||||
networkCurrency = userWalletManager.getNetworkCurrency(networkId),
|
||||
swapDataModel = swapStateData,
|
||||
|
|
@ -634,7 +698,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
@Suppress("LongParameterList")
|
||||
private suspend fun updatePermissionState(
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
swapAmount: SwapAmount,
|
||||
quotesLoadedState: SwapState.QuotesLoadedState,
|
||||
): SwapState.QuotesLoadedState {
|
||||
|
|
@ -691,7 +755,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun syncWalletBalanceForTokens(networkId: String, tokens: List<Currency>) {
|
||||
private suspend fun syncWalletBalanceForTokens(networkId: String, tokens: List<CryptoCurrency>) {
|
||||
val tokensToSync = tokens.filter { cache.getBalanceForToken(networkId, derivationPath, it.symbol) == null }
|
||||
if (tokensToSync.isNotEmpty()) {
|
||||
val tokensBalance =
|
||||
|
|
@ -746,12 +810,12 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
|
||||
private fun isBalanceEnough(
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
amount: SwapAmount,
|
||||
fee: BigDecimal?,
|
||||
): Boolean {
|
||||
val tokenBalance = getTokenBalance(networkId, fromToken).value
|
||||
return if (fromToken is Currency.NonNativeToken) {
|
||||
return if (fromToken is CryptoCurrency.Token) {
|
||||
tokenBalance >= amount.value
|
||||
} else {
|
||||
tokenBalance > amount.value.plus(fee ?: BigDecimal.ZERO)
|
||||
|
|
@ -762,12 +826,12 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
return userWalletManager.getWalletAddress(networkId, derivationPath)
|
||||
}
|
||||
|
||||
private fun getTokenAddress(currency: Currency): String {
|
||||
private fun getTokenAddress(currency: CryptoCurrency): String {
|
||||
return when (currency) {
|
||||
is Currency.NativeToken -> {
|
||||
is CryptoCurrency.Coin -> {
|
||||
DEFAULT_BLOCKCHAIN_INCH_ADDRESS
|
||||
}
|
||||
is Currency.NonNativeToken -> {
|
||||
is CryptoCurrency.Token -> {
|
||||
currency.contractAddress
|
||||
}
|
||||
}
|
||||
|
|
@ -777,7 +841,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
fee: BigDecimal?,
|
||||
spendAmount: SwapAmount,
|
||||
networkId: String,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
): Boolean {
|
||||
if (fee == null) {
|
||||
return false
|
||||
|
|
@ -785,12 +849,12 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
val nativeTokenBalance = userWalletManager.getNativeTokenBalance(networkId, derivationPath)
|
||||
val percentsToFeeIncrease = BigDecimal.ONE
|
||||
return when (fromToken) {
|
||||
is Currency.NativeToken -> {
|
||||
is CryptoCurrency.Coin -> {
|
||||
nativeTokenBalance?.let { balance ->
|
||||
return balance.value.minus(spendAmount.value) > fee.multiply(percentsToFeeIncrease)
|
||||
} ?: false
|
||||
}
|
||||
is Currency.NonNativeToken -> {
|
||||
is CryptoCurrency.Token -> {
|
||||
nativeTokenBalance?.let { balance ->
|
||||
return balance.value > fee.multiply(percentsToFeeIncrease)
|
||||
} ?: false
|
||||
|
|
@ -816,7 +880,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
private suspend fun getApproveData(
|
||||
networkId: String,
|
||||
derivationPath: String?,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
swapAmount: SwapAmount? = null,
|
||||
): String {
|
||||
return getSelectedWalletSyncUseCase().fold(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.domain.models.data.AggregatedSwapDataModel
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
|
|
@ -46,8 +44,6 @@ interface SwapRepository {
|
|||
*/
|
||||
fun getTangemFee(): Double
|
||||
|
||||
suspend fun getCryptoCurrency(userWallet: UserWallet, currency: Currency, network: Network): CryptoCurrency?
|
||||
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getAllowance(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -62,7 +58,7 @@ interface SwapRepository {
|
|||
userWalletId: UserWalletId,
|
||||
networkId: String,
|
||||
derivationPath: String?,
|
||||
currency: Currency,
|
||||
currency: CryptoCurrency,
|
||||
amount: BigDecimal?,
|
||||
): String
|
||||
}
|
||||
|
|
@ -2,19 +2,19 @@ package com.tangem.feature.swap.domain.cache
|
|||
|
||||
import com.tangem.feature.swap.domain.models.SwapAmount
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalance
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalanceExpress
|
||||
import java.math.BigDecimal
|
||||
|
||||
interface SwapDataCache {
|
||||
|
||||
fun cacheAvailableToSwapTokens(networkId: String, tokens: List<Currency>)
|
||||
fun cacheInWalletTokens(tokens: List<TokenWithBalance>)
|
||||
fun cacheLoadedTokens(tokens: List<TokenWithBalance>)
|
||||
fun cacheInWalletTokens(tokens: List<TokenWithBalanceExpress>)
|
||||
fun cacheLoadedTokens(tokens: List<TokenWithBalanceExpress>)
|
||||
fun cacheBalances(networkId: String, derivationPath: String?, balances: Map<String, SwapAmount>)
|
||||
fun cacheLastFeeForNetwork(fee: BigDecimal, networkId: String)
|
||||
fun getAvailableTokens(networkId: String): List<Currency>
|
||||
fun getInWalletTokens(): List<TokenWithBalance>
|
||||
fun getLoadedTokens(): List<TokenWithBalance>
|
||||
fun getInWalletTokens(): List<TokenWithBalanceExpress>
|
||||
fun getLoadedTokens(): List<TokenWithBalanceExpress>
|
||||
fun getBalanceForToken(networkId: String, derivationPath: String?, symbol: String): SwapAmount?
|
||||
fun getLastFeeForNetwork(networkId: String): BigDecimal?
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.tangem.feature.swap.domain.cache
|
|||
|
||||
import com.tangem.feature.swap.domain.models.SwapAmount
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalance
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalanceExpress
|
||||
import java.math.BigDecimal
|
||||
|
||||
class SwapDataCacheImpl : SwapDataCache {
|
||||
|
|
@ -10,28 +10,28 @@ class SwapDataCacheImpl : SwapDataCache {
|
|||
private val availableTokensForNetwork: MutableMap<String, List<Currency>> = mutableMapOf()
|
||||
private val feesForNetworks: MutableMap<String, BigDecimal> = mutableMapOf()
|
||||
private val tokensBalances: MutableMap<String, Map<String, SwapAmount>> = mutableMapOf()
|
||||
private val lastInWalletTokens = mutableListOf<TokenWithBalance>()
|
||||
private val lastLoadedTokens = mutableListOf<TokenWithBalance>()
|
||||
private val lastInWalletTokens = mutableListOf<TokenWithBalanceExpress>()
|
||||
private val lastLoadedTokens = mutableListOf<TokenWithBalanceExpress>()
|
||||
|
||||
override fun cacheLastFeeForNetwork(fee: BigDecimal, networkId: String) {
|
||||
feesForNetworks[networkId] = fee
|
||||
}
|
||||
|
||||
override fun cacheInWalletTokens(tokens: List<TokenWithBalance>) {
|
||||
override fun cacheInWalletTokens(tokens: List<TokenWithBalanceExpress>) {
|
||||
lastInWalletTokens.clear()
|
||||
lastInWalletTokens.addAll(tokens)
|
||||
}
|
||||
|
||||
override fun cacheLoadedTokens(tokens: List<TokenWithBalance>) {
|
||||
override fun cacheLoadedTokens(tokens: List<TokenWithBalanceExpress>) {
|
||||
lastLoadedTokens.clear()
|
||||
lastLoadedTokens.addAll(tokens)
|
||||
}
|
||||
|
||||
override fun getInWalletTokens(): List<TokenWithBalance> {
|
||||
override fun getInWalletTokens(): List<TokenWithBalanceExpress> {
|
||||
return lastInWalletTokens
|
||||
}
|
||||
|
||||
override fun getLoadedTokens(): List<TokenWithBalance> {
|
||||
override fun getLoadedTokens(): List<TokenWithBalanceExpress> {
|
||||
return lastLoadedTokens
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,54 +1,29 @@
|
|||
package com.tangem.feature.swap.domain.converters
|
||||
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
import com.tangem.lib.crypto.models.Currency as CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.lib.crypto.models.Currency
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class SwapCurrencyConverter : TwoWayConverter<Currency, CryptoCurrency> {
|
||||
class SwapCurrencyConverter : Converter<CryptoCurrency, Currency> {
|
||||
|
||||
override fun convert(value: Currency): CryptoCurrency {
|
||||
override fun convert(value: CryptoCurrency): Currency {
|
||||
return when (value) {
|
||||
is Currency.NonNativeToken -> {
|
||||
CryptoCurrency.NonNativeToken(
|
||||
id = value.id,
|
||||
name = value.name,
|
||||
symbol = value.symbol,
|
||||
networkId = value.networkId,
|
||||
contractAddress = value.contractAddress,
|
||||
decimalCount = value.decimalCount,
|
||||
)
|
||||
}
|
||||
is Currency.NativeToken -> {
|
||||
CryptoCurrency.NativeToken(
|
||||
id = value.id,
|
||||
name = value.name,
|
||||
symbol = value.symbol,
|
||||
networkId = value.networkId,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun convertBack(value: CryptoCurrency): Currency {
|
||||
return when (value) {
|
||||
is CryptoCurrency.NonNativeToken -> {
|
||||
is CryptoCurrency.Token -> {
|
||||
Currency.NonNativeToken(
|
||||
id = value.id,
|
||||
id = value.id.value,
|
||||
name = value.name,
|
||||
symbol = value.symbol,
|
||||
networkId = value.networkId,
|
||||
networkId = value.network.id.value,
|
||||
contractAddress = value.contractAddress,
|
||||
decimalCount = value.decimalCount,
|
||||
logoUrl = "",
|
||||
decimalCount = value.decimals,
|
||||
)
|
||||
}
|
||||
is CryptoCurrency.NativeToken -> {
|
||||
is CryptoCurrency.Coin -> {
|
||||
Currency.NativeToken(
|
||||
id = value.id,
|
||||
id = value.id.value,
|
||||
name = value.name,
|
||||
symbol = value.symbol,
|
||||
networkId = value.networkId,
|
||||
logoUrl = "",
|
||||
networkId = value.network.id.value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package com.tangem.feature.swap.domain.di
|
||||
|
||||
import com.tangem.domain.tokens.GetCardTokensListUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.feature.swap.domain.*
|
||||
|
|
@ -10,6 +13,7 @@ import com.tangem.feature.swap.domain.cache.SwapDataCacheImpl
|
|||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.lib.crypto.TransactionManager
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -31,7 +35,8 @@ class SwapDomainModule {
|
|||
networksRepository: NetworksRepository,
|
||||
walletFeatureToggles: WalletFeatureToggles,
|
||||
@SwapScope getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
@SwapScope getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
|
||||
@SwapScope getCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusUseCase,
|
||||
@SwapScope getCardTokensListUseCase: GetCardTokensListUseCase,
|
||||
): SwapInteractor {
|
||||
return SwapInteractorImpl(
|
||||
transactionManager = transactionManager,
|
||||
|
|
@ -43,14 +48,15 @@ class SwapDomainModule {
|
|||
networksRepository = networksRepository,
|
||||
walletFeatureToggles = walletFeatureToggles,
|
||||
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
|
||||
getCryptoCurrenciesUseCase = getCryptoCurrenciesUseCase,
|
||||
getMultiCryptoCurrencyStatusUseCase = getCryptoCurrencyStatusUseCase,
|
||||
getCardTokensListUseCase = getCardTokensListUseCase,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBlockchainInteractor(transactionManager: TransactionManager): BlockchainInteractor {
|
||||
return BlockchainInteractorImpl(
|
||||
return DefaultBlockchainInteractor(
|
||||
transactionManager = transactionManager,
|
||||
)
|
||||
}
|
||||
|
|
@ -68,6 +74,40 @@ class SwapDomainModule {
|
|||
fun providesGetCryptoCurrenciesUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrenciesUseCase {
|
||||
return GetCryptoCurrenciesUseCase(currenciesRepository = currenciesRepository)
|
||||
}
|
||||
|
||||
@SwapScope
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetCryptoCurrencyStatusUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCryptoCurrencyStatusUseCase {
|
||||
return GetCryptoCurrencyStatusUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@SwapScope
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetCardTokensListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCardTokensListUseCase {
|
||||
return GetCardTokensListUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Qualifier
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.domain.models.domain
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.ui.RequestApproveStateData
|
||||
import com.tangem.feature.swap.domain.models.ui.TxFee
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ import com.tangem.feature.swap.domain.models.ui.TxFee
|
|||
data class PermissionOptions(
|
||||
val approveData: RequestApproveStateData,
|
||||
val forTokenContractAddress: String,
|
||||
val fromToken: Currency,
|
||||
val fromToken: CryptoCurrency,
|
||||
val approveType: SwapApproveType,
|
||||
val txFee: TxFee,
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.feature.swap.domain.models.ui
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapPair
|
||||
|
||||
data class TokensDataStateExpress(
|
||||
val initialCryptoCurrency: CryptoCurrency,
|
||||
val preselectTokens: PreselectTokensExpress,
|
||||
val foundTokensState: FoundTokensStateExpress,
|
||||
val pairs: List<SwapPair>,
|
||||
)
|
||||
|
||||
data class FoundTokensStateExpress(
|
||||
val tokensInWallet: List<TokenWithBalanceExpress>,
|
||||
val loadedTokens: List<TokenWithBalanceExpress>,
|
||||
)
|
||||
|
||||
data class PreselectTokensExpress(
|
||||
val fromToken: CryptoCurrency,
|
||||
val toToken: CryptoCurrency,
|
||||
)
|
||||
|
||||
data class TokenWithBalanceExpress(
|
||||
val token: CryptoCurrency,
|
||||
val tokenBalanceData: TokenBalanceDataExpress? = null,
|
||||
)
|
||||
|
||||
data class TokenBalanceDataExpress(
|
||||
val amount: String?,
|
||||
val amountEquivalent: String?,
|
||||
)
|
||||
|
|
@ -2,10 +2,10 @@ package com.tangem.feature.swap.converters
|
|||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.NetworkInfo
|
||||
import com.tangem.feature.swap.domain.models.ui.FoundTokensState
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalance
|
||||
import com.tangem.feature.swap.domain.models.ui.FoundTokensStateExpress
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalanceExpress
|
||||
import com.tangem.feature.swap.models.Network
|
||||
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
|
||||
import com.tangem.feature.swap.models.TokenBalanceData
|
||||
|
|
@ -18,7 +18,7 @@ class TokensDataConverter(
|
|||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
) {
|
||||
|
||||
fun convertWithNetwork(value: FoundTokensState, network: NetworkInfo): SwapSelectTokenStateHolder {
|
||||
fun convertWithNetwork(value: FoundTokensStateExpress, network: NetworkInfo): SwapSelectTokenStateHolder {
|
||||
return SwapSelectTokenStateHolder(
|
||||
availableTokens = value.tokensInWallet.map { tokenWithBalanceToTokenToSelect(it) }.toImmutableList(),
|
||||
unavailableTokens = value.loadedTokens.map { tokenWithBalanceToTokenToSelect(it) }.toImmutableList(),
|
||||
|
|
@ -28,12 +28,14 @@ class TokensDataConverter(
|
|||
)
|
||||
}
|
||||
|
||||
private fun tokenWithBalanceToTokenToSelect(tokenWithBalance: TokenWithBalance): TokenToSelectState.TokenToSelect {
|
||||
private fun tokenWithBalanceToTokenToSelect(
|
||||
tokenWithBalance: TokenWithBalanceExpress,
|
||||
): TokenToSelectState.TokenToSelect {
|
||||
return TokenToSelectState.TokenToSelect(
|
||||
id = tokenWithBalance.token.id,
|
||||
id = tokenWithBalance.token.id.value,
|
||||
name = tokenWithBalance.token.name,
|
||||
symbol = tokenWithBalance.token.symbol,
|
||||
isNative = tokenWithBalance.token is Currency.NativeToken,
|
||||
isNative = tokenWithBalance.token is CryptoCurrency.Coin,
|
||||
// todo replace converting
|
||||
tokenIcon = TokenIconState.CoinIcon(
|
||||
url = "",
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ data class SwapCardData(
|
|||
val amountEquivalent: String?,
|
||||
val coinId: String?,
|
||||
val amountTextFieldValue: TextFieldValue?,
|
||||
val tokenIconUrl: String,
|
||||
val tokenIconUrl: String?,
|
||||
val tokenCurrency: String,
|
||||
val balance: String,
|
||||
val isBalanceHidden: Boolean,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.common.Provider
|
|||
import com.tangem.core.ui.components.states.Item
|
||||
import com.tangem.core.ui.components.states.SelectableItemsState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.converters.TokensDataConverter
|
||||
import com.tangem.feature.swap.domain.models.DataError
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
|
|
@ -73,21 +74,21 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider:
|
|||
|
||||
fun createQuotesLoadingState(
|
||||
uiStateHolder: SwapStateHolder,
|
||||
fromToken: Currency,
|
||||
toToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
mainTokenId: String,
|
||||
): SwapStateHolder {
|
||||
val canSelectSendToken = mainTokenId != fromToken.id
|
||||
val canSelectReceiveToken = mainTokenId != toToken.id
|
||||
val canSelectSendToken = mainTokenId != fromToken.id.value // TODO look at id matching
|
||||
val canSelectReceiveToken = mainTokenId != toToken.id.value // TODO look at id matching
|
||||
return uiStateHolder.copy(
|
||||
sendCardData = SwapCardData(
|
||||
type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard),
|
||||
amountTextFieldValue = uiStateHolder.sendCardData.amountTextFieldValue,
|
||||
amountEquivalent = null,
|
||||
tokenIconUrl = fromToken.logoUrl,
|
||||
tokenIconUrl = fromToken.iconUrl,
|
||||
tokenCurrency = fromToken.symbol,
|
||||
coinId = fromToken.id,
|
||||
isNotNativeToken = fromToken.isNonNative(),
|
||||
coinId = fromToken.id.value,
|
||||
isNotNativeToken = fromToken is CryptoCurrency.Token,
|
||||
canSelectAnotherToken = canSelectSendToken,
|
||||
balance = if (!canSelectSendToken) uiStateHolder.sendCardData.balance else "",
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
|
|
@ -96,10 +97,10 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider:
|
|||
type = TransactionCardType.ReceiveCard(),
|
||||
amountTextFieldValue = null,
|
||||
amountEquivalent = null,
|
||||
tokenIconUrl = toToken.logoUrl,
|
||||
tokenIconUrl = toToken.iconUrl,
|
||||
tokenCurrency = toToken.symbol,
|
||||
coinId = toToken.id,
|
||||
isNotNativeToken = toToken.isNonNative(),
|
||||
coinId = toToken.id.value,
|
||||
isNotNativeToken = toToken is CryptoCurrency.Token,
|
||||
canSelectAnotherToken = canSelectReceiveToken,
|
||||
balance = if (!canSelectReceiveToken) uiStateHolder.receiveCardData.balance else "",
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
|
|
@ -123,7 +124,7 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider:
|
|||
fun createQuotesLoadedState(
|
||||
uiStateHolder: SwapStateHolder,
|
||||
quoteModel: SwapState.QuotesLoadedState,
|
||||
fromToken: Currency,
|
||||
fromToken: CryptoCurrency,
|
||||
onFeeSetup: (TxFee) -> Unit,
|
||||
): SwapStateHolder {
|
||||
val warnings = mutableListOf<SwapWarning>()
|
||||
|
|
@ -238,7 +239,7 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider:
|
|||
|
||||
fun addTokensToState(
|
||||
uiState: SwapStateHolder,
|
||||
dataState: FoundTokensState,
|
||||
dataState: FoundTokensStateExpress,
|
||||
networkInfo: NetworkInfo,
|
||||
): SwapStateHolder {
|
||||
return uiState.copy(
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ private fun MainInfo(state: SwapStateHolder) {
|
|||
},
|
||||
textFieldValue = state.sendCardData.amountTextFieldValue,
|
||||
amountEquivalent = state.sendCardData.amountEquivalent,
|
||||
tokenIconUrl = state.sendCardData.tokenIconUrl,
|
||||
tokenIconUrl = state.sendCardData.tokenIconUrl ?: "",
|
||||
tokenCurrency = state.sendCardData.tokenCurrency,
|
||||
priceImpact = priceImpactWarning,
|
||||
networkIconRes = if (state.sendCardData.isNotNativeToken) networkIconRes else null,
|
||||
|
|
@ -169,7 +169,7 @@ private fun MainInfo(state: SwapStateHolder) {
|
|||
balance = if (state.receiveCardData.isBalanceHidden) STARS else state.receiveCardData.balance,
|
||||
textFieldValue = state.receiveCardData.amountTextFieldValue,
|
||||
amountEquivalent = state.receiveCardData.amountEquivalent,
|
||||
tokenIconUrl = state.receiveCardData.tokenIconUrl,
|
||||
tokenIconUrl = state.receiveCardData.tokenIconUrl ?: "",
|
||||
tokenCurrency = state.receiveCardData.tokenCurrency,
|
||||
priceImpact = priceImpactWarning,
|
||||
networkIconRes = if (state.receiveCardData.isNotNativeToken) networkIconRes else null,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.common.Provider
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.utils.InputNumberFormatter
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.feature.swap.analytics.SwapEvents
|
||||
import com.tangem.feature.swap.domain.BlockchainInteractor
|
||||
|
|
@ -51,10 +52,14 @@ internal class SwapViewModel @Inject constructor(
|
|||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver {
|
||||
|
||||
// try to get rid of this and use only CryptoCurrency
|
||||
private val currency = Json.decodeFromString<Currency>(
|
||||
savedStateHandle[SwapFragment.CURRENCY_BUNDLE_KEY]
|
||||
?: error("no expected parameter Currency found"),
|
||||
)
|
||||
|
||||
private var cryptoCurrency: CryptoCurrency by Delegates.notNull()
|
||||
|
||||
private val derivationPath = savedStateHandle.get<String>(SwapFragment.DERIVATION_PATH)
|
||||
private val network = savedStateHandle.get<Network>(SwapFragment.NETWORK)
|
||||
|
||||
|
|
@ -132,8 +137,21 @@ internal class SwapViewModel @Inject constructor(
|
|||
// new flow
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
runCatching(dispatchers.io) {
|
||||
val pairs = swapInteractor.getPairs(currency)
|
||||
// TODO
|
||||
swapInteractor.getTokensDataState(currency)
|
||||
}.onSuccess { state ->
|
||||
dataState = dataState.copy(
|
||||
fromCryptoCurrency = state.preselectTokens.fromToken,
|
||||
toCryptoCurrency = state.preselectTokens.toToken,
|
||||
)
|
||||
cryptoCurrency = state.initialCryptoCurrency
|
||||
// updateTokensState(dataState = state.foundTokensState)
|
||||
// startLoadingQuotes(
|
||||
// fromToken = state.preselectTokens.fromToken,
|
||||
// toToken = state.preselectTokens.toToken,
|
||||
// amount = lastAmount.value,
|
||||
// )
|
||||
}.onFailure {
|
||||
Timber.tag(loggingTag).e(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,24 +161,24 @@ internal class SwapViewModel @Inject constructor(
|
|||
swapInteractor.initTokensToSwap(currency)
|
||||
}
|
||||
.onSuccess { state ->
|
||||
dataState = dataState.copy(
|
||||
fromCurrency = state.preselectTokens.fromToken,
|
||||
toCurrency = state.preselectTokens.toToken,
|
||||
)
|
||||
updateTokensState(dataState = state.foundTokensState)
|
||||
startLoadingQuotes(
|
||||
fromToken = state.preselectTokens.fromToken,
|
||||
toToken = state.preselectTokens.toToken,
|
||||
amount = lastAmount.value,
|
||||
)
|
||||
// dataState = dataState.copy(
|
||||
// fromCurrency = state.preselectTokens.fromToken,
|
||||
// toCurrency = state.preselectTokens.toToken,
|
||||
// )
|
||||
// updateTokensState(dataState = state.foundTokensState)
|
||||
// startLoadingQuotes(
|
||||
// fromToken = state.preselectTokens.fromToken,
|
||||
// toToken = state.preselectTokens.toToken,
|
||||
// amount = lastAmount.value,
|
||||
// )
|
||||
}
|
||||
.onFailure {
|
||||
Timber.e(it)
|
||||
Timber.tag(loggingTag).e(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTokensState(dataState: FoundTokensState) {
|
||||
private fun updateTokensState(dataState: FoundTokensStateExpress) {
|
||||
uiState = stateBuilder.addTokensToState(
|
||||
uiState = uiState,
|
||||
dataState = dataState,
|
||||
|
|
@ -168,9 +186,9 @@ internal class SwapViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun startLoadingQuotes(fromToken: Currency, toToken: Currency, amount: String) {
|
||||
private fun startLoadingQuotes(fromToken: CryptoCurrency, toToken: CryptoCurrency, amount: String) {
|
||||
singleTaskScheduler.cancelTask()
|
||||
uiState = stateBuilder.createQuotesLoadingState(uiState, fromToken, toToken, currency.id)
|
||||
uiState = stateBuilder.createQuotesLoadingState(uiState, fromToken, toToken, cryptoCurrency.id.value)
|
||||
singleTaskScheduler.scheduleTask(
|
||||
viewModelScope,
|
||||
loadQuotesTask(
|
||||
|
|
@ -182,15 +200,19 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun startLoadingQuotesFromLastState() {
|
||||
val fromCurrency = dataState.fromCurrency
|
||||
val toCurrency = dataState.toCurrency
|
||||
val fromCurrency = dataState.fromCryptoCurrency
|
||||
val toCurrency = dataState.toCryptoCurrency
|
||||
val amount = dataState.amount
|
||||
if (fromCurrency != null && toCurrency != null && amount != null) {
|
||||
startLoadingQuotes(fromCurrency, toCurrency, amount)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadQuotesTask(fromToken: Currency, toToken: Currency, amount: String): PeriodicTask<SwapState> {
|
||||
private fun loadQuotesTask(
|
||||
fromToken: CryptoCurrency,
|
||||
toToken: CryptoCurrency,
|
||||
amount: String,
|
||||
): PeriodicTask<SwapState> {
|
||||
return PeriodicTask(
|
||||
UPDATE_DELAY,
|
||||
task = {
|
||||
|
|
@ -264,8 +286,8 @@ internal class SwapViewModel @Inject constructor(
|
|||
swapInteractor.onSwap(
|
||||
networkId = dataState.networkId,
|
||||
swapStateData = requireNotNull(dataState.swapDataModel),
|
||||
currencyToSend = requireNotNull(dataState.fromCurrency),
|
||||
currencyToGet = requireNotNull(dataState.toCurrency),
|
||||
currencyToSend = requireNotNull(dataState.fromCryptoCurrency),
|
||||
currencyToGet = requireNotNull(dataState.toCryptoCurrency),
|
||||
amountToSwap = requireNotNull(dataState.amount),
|
||||
fee = requireNotNull(dataState.selectedFee),
|
||||
)
|
||||
|
|
@ -314,9 +336,9 @@ internal class SwapViewModel @Inject constructor(
|
|||
approveData = requireNotNull(dataState.approveDataModel) {
|
||||
"dataState.approveDataModel might not be null"
|
||||
},
|
||||
forTokenContractAddress = (dataState.fromCurrency as? Currency.NonNativeToken)?.contractAddress
|
||||
forTokenContractAddress = (dataState.fromCryptoCurrency as? CryptoCurrency.Token)?.contractAddress
|
||||
?: "",
|
||||
fromToken = requireNotNull(dataState.fromCurrency) {
|
||||
fromToken = requireNotNull(dataState.fromCryptoCurrency) {
|
||||
"dataState.fromCurrency might not be null"
|
||||
},
|
||||
approveType = requireNotNull(uiState.permissionState as? SwapPermissionState.ReadyForRequest) {
|
||||
|
|
@ -367,18 +389,18 @@ internal class SwapViewModel @Inject constructor(
|
|||
)
|
||||
|
||||
if (foundToken != null) {
|
||||
val fromToken: Currency
|
||||
val toToken: Currency
|
||||
val fromToken: CryptoCurrency
|
||||
val toToken: CryptoCurrency
|
||||
if (isOrderReversed) {
|
||||
fromToken = foundToken
|
||||
toToken = currency
|
||||
toToken = cryptoCurrency
|
||||
} else {
|
||||
fromToken = currency
|
||||
fromToken = cryptoCurrency
|
||||
toToken = foundToken
|
||||
}
|
||||
dataState = dataState.copy(
|
||||
fromCurrency = fromToken,
|
||||
toCurrency = toToken,
|
||||
fromCryptoCurrency = fromToken,
|
||||
toCryptoCurrency = toToken,
|
||||
)
|
||||
startLoadingQuotes(fromToken, toToken, lastAmount.value)
|
||||
swapRouter.openScreen(SwapNavScreen.Main)
|
||||
|
|
@ -386,12 +408,12 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onChangeCardsClicked() {
|
||||
val newFromToken = dataState.toCurrency
|
||||
val newToToken = dataState.fromCurrency
|
||||
val newFromToken = dataState.toCryptoCurrency
|
||||
val newToToken = dataState.fromCryptoCurrency
|
||||
if (newFromToken != null && newToToken != null) {
|
||||
dataState = dataState.copy(
|
||||
fromCurrency = newFromToken,
|
||||
toCurrency = newToToken,
|
||||
fromCryptoCurrency = newFromToken,
|
||||
toCryptoCurrency = newToToken,
|
||||
)
|
||||
isOrderReversed = !isOrderReversed
|
||||
val decimals = blockchainInteractor.getTokenDecimals(newFromToken)
|
||||
|
|
@ -405,8 +427,8 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onAmountChanged(value: String) {
|
||||
val fromToken = dataState.fromCurrency
|
||||
val toToken = dataState.toCurrency
|
||||
val fromToken = dataState.fromCryptoCurrency
|
||||
val toToken = dataState.toCryptoCurrency
|
||||
if (fromToken != null && toToken != null) {
|
||||
val decimals = blockchainInteractor.getTokenDecimals(fromToken)
|
||||
val cutValue = cutAmountWithDecimals(decimals, value)
|
||||
|
|
@ -420,8 +442,8 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onMaxAmountClicked() {
|
||||
dataState.fromCurrency?.let {
|
||||
val balance = swapInteractor.getTokenBalance(currency.networkId, it)
|
||||
dataState.fromCryptoCurrency?.let {
|
||||
val balance = swapInteractor.getTokenBalance(cryptoCurrency.network.id.value, it)
|
||||
onAmountChanged(balance.formatToUIRepresentation())
|
||||
}
|
||||
}
|
||||
|
|
@ -496,11 +518,11 @@ internal class SwapViewModel @Inject constructor(
|
|||
onSelectItemFee = { feeItem ->
|
||||
dataState = dataState.copy(selectedFee = feeItem.data)
|
||||
val spendAmount = dataState.amount?.let { amount ->
|
||||
val fromToken = dataState.fromCurrency ?: return@let null
|
||||
val fromToken = dataState.fromCryptoCurrency ?: return@let null
|
||||
swapInteractor.getSwapAmountForToken(amount, fromToken)
|
||||
} ?: dataState.approveDataModel?.fromTokenAmount
|
||||
spendAmount ?: return@UiActions
|
||||
val fromToken = dataState.fromCurrency ?: return@UiActions
|
||||
val fromToken = dataState.fromCryptoCurrency ?: return@UiActions
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val isFeeEnough = swapInteractor.checkFeeIsEnough(
|
||||
fee = feeItem.data.feeValue,
|
||||
|
|
@ -517,6 +539,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val loggingTag = "SwapViewModel"
|
||||
private const val INITIAL_AMOUNT = ""
|
||||
private const val UPDATE_DELAY = 10000L
|
||||
private const val DEBOUNCE_AMOUNT_DELAY = 1000L
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue