Updated on 2026-08-14

This commit is contained in:
Tangem 2023-01-12 16:54:51 +03:00
parent c6dac76deb
commit fa2d958fff
30 changed files with 248 additions and 75 deletions

View file

@ -39,6 +39,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
globalState.copy(scanResponse = action.scanResponse)
}
is GlobalAction.ChangeAppCurrency -> {
appStateHolder.appFiatCurrency = action.appCurrency
globalState.copy(appCurrency = action.appCurrency)
}
is GlobalAction.RestoreAppCurrency.Success -> {

View file

@ -28,7 +28,7 @@ import com.tangem.tap.store
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import com.tangem.feature.swap.domain.models.data.Currency as SwapCurrency
import com.tangem.feature.swap.domain.models.Currency as SwapCurrency
class TradeCryptoMiddleware {
fun handle(state: () -> AppState?, action: WalletAction.TradeCryptoAction) {

View file

@ -3,6 +3,7 @@ package com.tangem.tap.proxy
import com.tangem.TangemSdk
import com.tangem.domain.common.CardDTO
import com.tangem.domain.common.ScanResponse
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.TangemSdkManager
import com.tangem.tap.domain.tokens.UserTokensRepository
@ -16,7 +17,7 @@ import javax.inject.Inject
* Holds objects from old modules, that missing in DI graph
* Object sets manually to use in new modules and [AppStateHolder] proxies its to DI
*/
class AppStateHolder @Inject constructor(){
class AppStateHolder @Inject constructor() {
var scanResponse: ScanResponse? = null
var walletState: WalletState? = null
@ -26,6 +27,7 @@ class AppStateHolder @Inject constructor(){
var tangemSdk: TangemSdk? = null
var walletStoresManager: WalletStoresManager? = null
var userWalletsListManager: UserWalletsListManager? = null
var appFiatCurrency: FiatCurrency = FiatCurrency.Default
fun getActualCard(): CardDTO? {
return scanResponse?.card

View file

@ -3,6 +3,7 @@ package com.tangem.tap.proxy
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationParams
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.domain.common.CardDTO
import com.tangem.domain.common.TapWorkarounds.derivationStyle
@ -12,11 +13,14 @@ import com.tangem.lib.crypto.UserWalletManager
import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.Currency.NativeToken
import com.tangem.lib.crypto.models.Currency.NonNativeToken
import com.tangem.lib.crypto.models.ProxyAmount
import com.tangem.lib.crypto.models.ProxyFiatCurrency
import com.tangem.tap.domain.extensions.makeWalletManagerForApp
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.wallet.redux.WalletAction
import org.rekotlin.Action
import java.math.BigDecimal
class UserWalletManagerImpl(
private val appStateHolder: AppStateHolder,
@ -105,6 +109,28 @@ class UserWalletManagerImpl(
}
}
override fun getCurrentWalletTokensBalance(networkId: String): Map<String, ProxyAmount> {
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
val walletManager = getActualWalletManager(blockchain)
return walletManager.wallet.amounts.map { entry ->
val amount = entry.value
amount.currencySymbol to ProxyAmount(
amount.currencySymbol,
amount.value ?: BigDecimal.ZERO,
amount.decimals,
)
}.toMap()
}
override fun getUserAppCurrency(): ProxyFiatCurrency {
val appCurrency = appStateHolder.appFiatCurrency
return ProxyFiatCurrency(
code = appCurrency.code,
name = appCurrency.name,
symbol = appCurrency.symbol,
)
}
private fun addNativeTokenToWalletAction(token: NativeToken, card: CardDTO): Action {
val blockchain = Blockchain.fromNetworkId(token.networkId)
val scanResponse = appStateHolder.scanResponse
@ -154,4 +180,10 @@ class UserWalletManagerImpl(
private fun createDerivationParams(derivationStyle: DerivationStyle?): DerivationParams? {
return derivationStyle?.let { DerivationParams.Default(derivationStyle) } //todo clarify if its need to add Custom
}
private fun getActualWalletManager(blockchain: Blockchain): WalletManager {
val card = requireNotNull(appStateHolder.getActualCard()) { "card not found" }
val blockchainNetwork = BlockchainNetwork(blockchain, card)
return requireNotNull(appStateHolder.walletState?.getWalletManager(blockchainNetwork)) { "no wallet manager found" }
}
}

View file

@ -6,6 +6,7 @@ import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*
//todo determine where to place this extensions
fun BigDecimal.toFormattedString(
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US,
): String {
@ -18,4 +19,51 @@ fun BigDecimal.toFormattedString(
this.roundingMode = roundingMode
}
return df.format(this)
}
fun BigDecimal.toFiatString(
rateValue: BigDecimal,
fiatCurrencyName: String,
formatWithSpaces: Boolean = false
): String {
val fiatValue = rateValue.multiply(this)
return fiatValue.toFormattedFiatValue(fiatCurrencyName, formatWithSpaces)
}
fun BigDecimal.toFormattedFiatValue(
fiatCurrencyName: String,
formatWithSpaces: Boolean = false
): String {
val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
.let { if (formatWithSpaces) it.formatWithSpaces() else it }
return "${fiatValue} $fiatCurrencyName"
}
fun BigDecimal.formatWithSpaces(): String {
val str = this.toString()
var integerStr = str.substringBefore('.')
val reminderStr = str.substringAfter('.')
val packets = arrayListOf<String>()
var index: Int = integerStr.length
while (0 < index) {
if (index <= 3) {
packets.add(integerStr)
break
}
index -= 3
packets.add(integerStr.substring(startIndex = index))
integerStr = integerStr.substring(startIndex = 0, endIndex = index)
}
return buildString {
packets.reversed().forEachIndexed { index, packet ->
append(packet)
if (index != packets.lastIndex) append(' ')
}
if (reminderStr.isNotBlank()) {
append('.')
append(reminderStr)
}
}
}

View file

@ -10,12 +10,12 @@ import com.tangem.feature.swap.converters.QuotesConverter
import com.tangem.feature.swap.converters.SwapConverter
import com.tangem.feature.swap.converters.TokensConverter
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.SwapDataModel
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
import com.tangem.feature.swap.domain.models.data.mapErrors
import com.tangem.feature.swap.domain.models.ApproveModel
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapDataModel
import com.tangem.feature.swap.domain.models.data.AggregatedSwapDataModel
import com.tangem.feature.swap.domain.models.mapErrors
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import javax.inject.Inject
@ -31,6 +31,12 @@ internal class SwapRepositoryImpl @Inject constructor(
private val coroutineDispatcher: CoroutineDispatcherProvider,
) : SwapRepository {
override suspend fun getRates(currencyId: String, tokenIds: List<String>): Map<String, Double> {
return withContext(coroutineDispatcher.io) {
tangemTechApi.getRates(currencyId.lowercase(), tokenIds.joinToString(",")).rates
}
}
override suspend fun getExchangeableTokens(networkId: String): List<Currency> {
return withContext(coroutineDispatcher.io) {
tokensConverter.convertList(tangemTechApi.getCoins(exchangeable = true, networkIds = networkId).coins)

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.oneinch.models.ApproveCalldataResponse
import com.tangem.feature.swap.domain.models.data.ApproveModel
import com.tangem.feature.swap.domain.models.ApproveModel
import com.tangem.utils.converter.Converter
import javax.inject.Inject

View file

@ -1,8 +1,8 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.oneinch.models.QuoteResponse
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
import com.tangem.feature.swap.domain.models.data.createFromAmountWithOffset
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.createFromAmountWithOffset
import com.tangem.utils.converter.Converter
import javax.inject.Inject

View file

@ -2,8 +2,8 @@ package com.tangem.feature.swap.converters
import com.tangem.datasource.api.oneinch.models.SwapResponse
import com.tangem.datasource.api.oneinch.models.TransactionDto
import com.tangem.feature.swap.domain.models.data.SwapDataModel
import com.tangem.feature.swap.domain.models.data.TransactionModel
import com.tangem.feature.swap.domain.models.SwapDataModel
import com.tangem.feature.swap.domain.models.TransactionModel
import com.tangem.utils.converter.Converter
import javax.inject.Inject

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.converters
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.utils.converter.Converter
import javax.inject.Inject

View file

@ -1,15 +1,13 @@
package com.tangem.feature.swap.domain
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.data.SwapAmount
import com.tangem.feature.swap.domain.models.data.SwapState
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.SwapState
interface SwapInteractor {
suspend fun getTokensToSwap(networkId: String): List<Currency>
suspend fun getTokenBalance(tokenId: String): String
@Throws(IllegalStateException::class)
suspend fun givePermissionToSwap(tokenToApprove: Currency)

View file

@ -2,14 +2,17 @@ package com.tangem.feature.swap.domain
import com.tangem.feature.swap.domain.cache.SwapDataCache
import com.tangem.feature.swap.domain.converters.CryptoCurrencyConverter
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.data.DataError
import com.tangem.feature.swap.domain.models.data.SwapAmount
import com.tangem.feature.swap.domain.models.data.SwapState
import com.tangem.feature.swap.domain.models.data.TransactionModel
import com.tangem.feature.swap.domain.models.data.toStringWithRightOffset
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.DataError
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.SwapState
import com.tangem.feature.swap.domain.models.TransactionModel
import com.tangem.feature.swap.domain.models.toStringWithRightOffset
import com.tangem.lib.crypto.TransactionManager
import com.tangem.lib.crypto.UserWalletManager
import com.tangem.utils.toFiatString
import com.tangem.utils.toFormattedString
import java.math.BigDecimal
import javax.inject.Inject
@ -32,10 +35,6 @@ internal class SwapInteractorImpl @Inject constructor(
}
}
override suspend fun getTokenBalance(tokenId: String): String {
TODO("Not yet implemented")
}
override suspend fun givePermissionToSwap(tokenToApprove: Currency) {
cache.getNetworkId()?.let { networkId ->
if (tokenToApprove is Currency.NonNativeToken) {
@ -85,7 +84,7 @@ internal class SwapInteractorImpl @Inject constructor(
fromCurrency = fromToken,
toCurrency = toToken,
)
return quoteDataModel
return updateBalances(networkId, fromToken, toToken, quoteDataModel)
} else {
return SwapState.SwapError(quotes.error)
}
@ -129,6 +128,41 @@ internal class SwapInteractorImpl @Inject constructor(
}
}
private suspend fun updateBalances(
networkId: String,
fromToken: Currency,
toToken: Currency,
quoteModel: QuoteModel,
): SwapState.QuotesLoadedState {
val appCurrency = userWalletManager.getUserAppCurrency()
val rates = repository.getRates(appCurrency.code, listOf(fromToken.id, toToken.id))
val tokensBalance = userWalletManager.getCurrentWalletTokensBalance(networkId)
val fromTokenBalance = tokensBalance[fromToken.symbol]?.let {
it.value.toFormattedString(it.decimals)
}
val toTokenBalance = tokensBalance[toToken.symbol]?.let {
it.value.toFormattedString(it.decimals)
}
return SwapState.QuotesLoadedState(
fromTokenAmount = quoteModel.fromTokenAmount,
toTokenAmount = quoteModel.toTokenAmount,
fromTokenAddress = quoteModel.fromTokenAddress,
toTokenAddress = quoteModel.toTokenAddress,
estimatedGas = quoteModel.estimatedGas,
isAllowedToSpend = quoteModel.isAllowedToSpend,
fromTokenWalletBalance = fromTokenBalance ?: ZERO_BALANCE,
fromTokenFiatBalance = quoteModel.fromTokenAmount.value.toFiatString(
rates[fromToken.id]?.toBigDecimal() ?: BigDecimal.ZERO,
appCurrency.symbol,
),
toTokenWalletBalance = toTokenBalance ?: ZERO_BALANCE,
toTokenFiatBalance = quoteModel.fromTokenAmount.value.toFiatString(
rates[fromToken.id]?.toBigDecimal() ?: BigDecimal.ZERO,
appCurrency.symbol,
),
)
}
private fun getWalletAddress(networkId: String): String {
return userWalletManager.getWalletAddress(networkId)
}
@ -150,5 +184,6 @@ internal class SwapInteractorImpl @Inject constructor(
companion object {
private const val DEFAULT_SLIPPAGE = 2
private const val ZERO_BALANCE = "0"
}
}

View file

@ -1,13 +1,15 @@
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.SwapDataModel
import com.tangem.feature.swap.domain.models.data.SwapState
import com.tangem.feature.swap.domain.models.ApproveModel
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapDataModel
import com.tangem.feature.swap.domain.models.data.AggregatedSwapDataModel
interface SwapRepository {
suspend fun getRates(currencyId: String, tokenIds: List<String>): Map<String, Double>
suspend fun getExchangeableTokens(networkId: String): List<Currency>
suspend fun findBestQuote(
@ -15,7 +17,7 @@ interface SwapRepository {
fromTokenAddress: String,
toTokenAddress: String,
amount: String,
): AggregatedSwapDataModel<SwapState.QuoteModel>
): AggregatedSwapDataModel<QuoteModel>
/**
* Returns address of 1inch router that must be trusted

View file

@ -1,9 +1,9 @@
package com.tangem.feature.swap.domain.cache
import com.tangem.feature.swap.domain.models.ExchangeCurrencies
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.data.SwapAmount
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.cache.ExchangeCurrencies
interface SwapDataCache {

View file

@ -1,10 +1,10 @@
package com.tangem.feature.swap.domain.cache
import com.tangem.feature.swap.domain.models.ExchangeCurrencies
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.SwapAmount
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.cache.ExchangeCurrencies
import com.tangem.feature.swap.domain.models.cache.SwapDataHolder
class SwapDataCacheImpl : SwapDataCache {

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.domain.converters
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.utils.converter.Converter
class CryptoCurrencyConverter : Converter<Currency, com.tangem.lib.crypto.models.Currency> {

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
/**
* Approve model

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
import kotlinx.serialization.Serializable

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
enum class DataError {
NO_ERROR,

View file

@ -0,0 +1,20 @@
package com.tangem.feature.swap.domain.models
/**
* Quote model holds data about current amounts of exchange and fees
*
* @property fromTokenAmount amount of token you want to exchange
* @property toTokenAmount amount of token you want to receive
* @property fromTokenAddress address token you want to exchange
* @property toTokenAddress address token you want to receive
* @property estimatedGas fee
* @property isAllowedToSpend does spend allowed
*/
data class QuoteModel(
val fromTokenAmount: SwapAmount,
val toTokenAmount: SwapAmount,
val fromTokenAddress: String,
val toTokenAddress: String,
val estimatedGas: Int,
val isAllowedToSpend: Boolean = false,
)

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
import com.tangem.utils.toFormattedString
import java.math.BigDecimal

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
/**
* Swap transaction model

View file

@ -1,12 +1,16 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
sealed interface SwapState {
data class QuoteModel(
data class QuotesLoadedState(
val fromTokenAmount: SwapAmount,
val toTokenAmount: SwapAmount,
val fromTokenAddress: String,
val toTokenAddress: String,
val fromTokenWalletBalance: String,
val fromTokenFiatBalance: String,
val toTokenWalletBalance: String,
val toTokenFiatBalance: String,
val estimatedGas: Int,
val isAllowedToSpend: Boolean = false,
) : SwapState

View file

@ -1,4 +1,4 @@
package com.tangem.feature.swap.domain.models.data
package com.tangem.feature.swap.domain.models
/**
* Transaction model

View file

@ -1,9 +1,8 @@
package com.tangem.feature.swap.domain.models
package com.tangem.feature.swap.domain.models.cache
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.data.SwapAmount
import com.tangem.feature.swap.domain.models.data.SwapState.QuoteModel
import java.math.BigDecimal
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.QuoteModel
import com.tangem.feature.swap.domain.models.SwapAmount
data class SwapDataHolder(
val quoteModel: QuoteModel? = null,

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.domain.models
package com.tangem.feature.swap.domain.models.data
import com.tangem.feature.swap.domain.models.data.DataError
import com.tangem.feature.swap.domain.models.DataError
/**
* Model that aggregate data model from repository return with error [DataError] if it exists

View file

@ -1,8 +1,8 @@
package com.tangem.feature.swap.ui
import com.tangem.feature.swap.domain.models.data.Currency
import com.tangem.feature.swap.domain.models.data.SwapState
import com.tangem.feature.swap.domain.models.data.formatToUIRepresentation
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.SwapState
import com.tangem.feature.swap.domain.models.formatToUIRepresentation
import com.tangem.feature.swap.models.FeeState
import com.tangem.feature.swap.models.SwapButton
import com.tangem.feature.swap.models.SwapCardData
@ -50,7 +50,7 @@ class StateBuilder {
): SwapStateHolder {
return uiStateHolder.copy(
sendCardData = SwapCardData(
type = (uiStateHolder.sendCardData.type as TransactionCardType.SendCard),
type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard),
amount = uiStateHolder.sendCardData.amount,
amountEquivalent = uiStateHolder.sendCardData.amountEquivalent,
tokenIconUrl = fromToken.logoUrl,
@ -72,16 +72,19 @@ class StateBuilder {
fun createQuotesLoadedState(
uiStateHolder: SwapStateHolder,
quoteModel: SwapState.QuoteModel,
quoteModel: SwapState.QuotesLoadedState,
fromToken: Currency,
onSwapClick: () -> Unit,
): SwapStateHolder {
return uiStateHolder.copy(
sendCardData = SwapCardData(
type = (uiStateHolder.sendCardData.type as TransactionCardType.SendCard)
.copy(permissionIsGiven = quoteModel.isAllowedToSpend),
type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard)
.copy(
permissionIsGiven = quoteModel.isAllowedToSpend,
balance = quoteModel.fromTokenWalletBalance,
),
amount = quoteModel.fromTokenAmount.formatToUIRepresentation(),
amountEquivalent = uiStateHolder.sendCardData.amountEquivalent,
amountEquivalent = quoteModel.fromTokenFiatBalance,
tokenIconUrl = uiStateHolder.sendCardData.tokenIconUrl,
tokenCurrency = uiStateHolder.sendCardData.tokenCurrency,
canSelectAnotherToken = uiStateHolder.sendCardData.canSelectAnotherToken,
@ -89,7 +92,7 @@ class StateBuilder {
receiveCardData = SwapCardData(
type = TransactionCardType.ReceiveCard(),
amount = quoteModel.toTokenAmount.formatToUIRepresentation(),
amountEquivalent = uiStateHolder.receiveCardData.amountEquivalent,
amountEquivalent = quoteModel.toTokenFiatBalance,
tokenIconUrl = uiStateHolder.receiveCardData.tokenIconUrl,
tokenCurrency = uiStateHolder.receiveCardData.tokenCurrency,
canSelectAnotherToken = uiStateHolder.receiveCardData.canSelectAnotherToken,

View file

@ -8,9 +8,9 @@ import androidx.lifecycle.SavedStateHandle
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.feature.swap.domain.models.data.SwapState
import com.tangem.feature.swap.domain.models.data.createFromAmountWithoutOffset
import com.tangem.feature.swap.domain.models.Currency
import com.tangem.feature.swap.domain.models.SwapState
import com.tangem.feature.swap.domain.models.createFromAmountWithoutOffset
import com.tangem.feature.swap.models.SwapStateHolder
import com.tangem.feature.swap.presentation.SwapFragment
import com.tangem.feature.swap.router.SwapRouter
@ -97,7 +97,7 @@ internal class SwapViewModel @Inject constructor(
}
.onSuccess { swapState ->
when (swapState) {
is SwapState.QuoteModel -> {
is SwapState.QuotesLoadedState -> {
uiState = stateBuilder.createQuotesLoadedState(uiState, swapState, fromToken) {
onSwapClick(toToken, swapState)
}
@ -113,7 +113,7 @@ internal class SwapViewModel @Inject constructor(
}
}
private fun onSwapClick(toToken: Currency, quoteModel: SwapState.QuoteModel) {
private fun onSwapClick(toToken: Currency, quoteModel: SwapState.QuotesLoadedState) {
viewModelScope.launch(dispatchers.main) {
runCatching {
if (!quoteModel.isAllowedToSpend) {

View file

@ -1,6 +1,8 @@
package com.tangem.lib.crypto
import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.ProxyAmount
import com.tangem.lib.crypto.models.ProxyFiatCurrency
/**
* Provider for user tokens data
@ -37,4 +39,18 @@ interface UserWalletManager {
* @param networkId for currency
*/
fun getWalletAddress(networkId: String): String
/**
* Return balances from wallet found by networkId
*
* @param networkId
* @return map of <Symbol, [ProxyAmount]>
*/
@Throws(IllegalStateException::class)
fun getCurrentWalletTokensBalance(networkId: String): Map<String, ProxyAmount>
/**
* Returns selected app currency
*/
fun getUserAppCurrency(): ProxyFiatCurrency
}

View file

@ -0,0 +1,7 @@
package com.tangem.lib.crypto.models
data class ProxyFiatCurrency(
val code: String,
val name: String,
val symbol: String,
)