Updated on 2026-08-14
This commit is contained in:
commit
cf4dc83d0d
30 changed files with 248 additions and 75 deletions
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
/**
|
||||
* Approve model
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
enum class DataError {
|
||||
NO_ERROR,
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
/**
|
||||
* Swap transaction model
|
||||
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.swap.domain.models.data
|
||||
package com.tangem.feature.swap.domain.models
|
||||
|
||||
/**
|
||||
* Transaction model
|
||||
|
|
@ -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,
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
data class ProxyFiatCurrency(
|
||||
val code: String,
|
||||
val name: String,
|
||||
val symbol: String,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue