Updated on 2026-08-14
This commit is contained in:
parent
4f81761d27
commit
92e038b04f
17 changed files with 262 additions and 155 deletions
|
|
@ -20,6 +20,13 @@ class CryptoCurrencyToIconStateConverter : Converter<CryptoCurrencyStatus, Token
|
|||
}
|
||||
}
|
||||
|
||||
fun convert(currency: CryptoCurrency): TokenIconState {
|
||||
return when (currency) {
|
||||
is CryptoCurrency.Coin -> getIconStateForCoin(currency, isUnreachable = false)
|
||||
is CryptoCurrency.Token -> getIconStateForToken(currency, isErrorStatus = false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIconStateForCoin(coin: CryptoCurrency.Coin, isUnreachable: Boolean): TokenIconState.CoinIcon {
|
||||
return TokenIconState.CoinIcon(
|
||||
url = coin.iconUrl,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency
|
|||
import timber.log.Timber
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
||||
internal class ResponseCryptoCurrenciesFactory {
|
||||
class ResponseCryptoCurrenciesFactory {
|
||||
|
||||
fun createCurrency(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
||||
internal class UserTokensResponseFactory {
|
||||
class UserTokensResponseFactory {
|
||||
|
||||
fun createUserTokensResponse(
|
||||
currencies: List<CryptoCurrency>,
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ import com.tangem.datasource.local.preferences.PreferencesKeys
|
|||
import com.tangem.datasource.local.preferences.utils.getObjectList
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectListSync
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.converters.SavedSwapTransactionListConverter
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedLastSwappedCryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -20,23 +19,25 @@ class DefaultSwapTransactionRepository(
|
|||
private val appPreferencesStore: AppPreferencesStore,
|
||||
) : SwapTransactionRepository {
|
||||
|
||||
private val converter = SavedSwapTransactionListConverter()
|
||||
|
||||
override suspend fun storeTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
transaction: SavedSwapTransactionModel,
|
||||
) {
|
||||
transaction.status?.let { storeTransactionState(transaction.txId, it) }
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
val savedTransactions: List<SavedSwapTransactionListModel>? = mutablePreferences.getObjectList(
|
||||
val savedTransactions: List<SavedSwapTransactionListModelInner>? = mutablePreferences.getObjectList(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
)
|
||||
val tokenTransactions = savedTransactions
|
||||
?.firstOrNull {
|
||||
it.checkId(
|
||||
checkUserWalletId = userWalletId,
|
||||
fromCurrencyId = fromCryptoCurrencyId,
|
||||
toCurrencyId = toCryptoCurrencyId,
|
||||
fromCurrencyId = fromCryptoCurrency.id,
|
||||
toCurrencyId = toCryptoCurrency.id,
|
||||
)
|
||||
}
|
||||
?.transactions
|
||||
|
|
@ -49,15 +50,15 @@ class DefaultSwapTransactionRepository(
|
|||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
value = savedTransactions?.updateList(
|
||||
userWalletId = userWalletId,
|
||||
fromCryptoCurrencyId = fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = toCryptoCurrencyId,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
transactions = tokenTransactions,
|
||||
) ?: listOf(
|
||||
SavedSwapTransactionListModel(
|
||||
userWalletId = userWalletId.stringValue,
|
||||
fromCryptoCurrencyId = fromCryptoCurrencyId.value,
|
||||
toCryptoCurrencyId = toCryptoCurrencyId.value,
|
||||
transactions = tokenTransactions,
|
||||
converter.default(
|
||||
userWalletId = userWalletId,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
tokenTransactions = listOf(transaction),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -67,11 +68,12 @@ class DefaultSwapTransactionRepository(
|
|||
override suspend fun getTransactions(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
scanResponse: ScanResponse,
|
||||
): Flow<List<SavedSwapTransactionListModel>?> {
|
||||
val txStatuses = appPreferencesStore.getObjectMap<ExchangeStatusModel>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||
)
|
||||
return appPreferencesStore.getObjectList<SavedSwapTransactionListModel>(
|
||||
return appPreferencesStore.getObjectList<SavedSwapTransactionListModelInner>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
).map { savedTransactions ->
|
||||
val currencyTxs = savedTransactions
|
||||
|
|
@ -83,11 +85,11 @@ class DefaultSwapTransactionRepository(
|
|||
)
|
||||
}
|
||||
|
||||
currencyTxs?.map { currencyTx ->
|
||||
currencyTx.copy(
|
||||
transactions = currencyTx.transactions.map { tx ->
|
||||
tx.copy(status = txStatuses[tx.txId])
|
||||
},
|
||||
currencyTxs?.mapNotNull {
|
||||
converter.convertBack(
|
||||
value = it,
|
||||
scanResponse = scanResponse,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -95,21 +97,21 @@ class DefaultSwapTransactionRepository(
|
|||
|
||||
override suspend fun removeTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
txId: String,
|
||||
) {
|
||||
clearTransactionsStatuses(txId = txId)
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
val savedList: List<SavedSwapTransactionListModel>? = mutablePreferences.getObjectList(
|
||||
val savedList: List<SavedSwapTransactionListModelInner>? = mutablePreferences.getObjectList(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
)
|
||||
val tokenTransactions = savedList
|
||||
?.first {
|
||||
?.firstOrNull {
|
||||
it.checkId(
|
||||
checkUserWalletId = userWalletId,
|
||||
fromCurrencyId = fromCryptoCurrencyId,
|
||||
toCurrencyId = toCryptoCurrencyId,
|
||||
fromCurrencyId = fromCryptoCurrency.id,
|
||||
toCurrencyId = toCryptoCurrency.id,
|
||||
)
|
||||
}
|
||||
?.transactions
|
||||
|
|
@ -120,15 +122,15 @@ class DefaultSwapTransactionRepository(
|
|||
savedList?.filterNot {
|
||||
it.checkId(
|
||||
checkUserWalletId = userWalletId,
|
||||
fromCurrencyId = fromCryptoCurrencyId,
|
||||
toCurrencyId = toCryptoCurrencyId,
|
||||
fromCurrencyId = fromCryptoCurrency.id,
|
||||
toCurrencyId = toCryptoCurrency.id,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
savedList.updateList(
|
||||
userWalletId = userWalletId,
|
||||
fromCryptoCurrencyId = fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = toCryptoCurrencyId,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
transactions = tokenTransactions,
|
||||
)
|
||||
}
|
||||
|
|
@ -192,7 +194,7 @@ class DefaultSwapTransactionRepository(
|
|||
}
|
||||
}
|
||||
|
||||
private fun SavedSwapTransactionListModel.checkId(
|
||||
private fun SavedSwapTransactionListModelInner.checkId(
|
||||
checkUserWalletId: UserWalletId,
|
||||
fromCurrencyId: CryptoCurrency.ID,
|
||||
toCurrencyId: CryptoCurrency.ID,
|
||||
|
|
@ -202,24 +204,24 @@ class DefaultSwapTransactionRepository(
|
|||
fromCryptoCurrencyId == fromCurrencyId.value
|
||||
}
|
||||
|
||||
private fun List<SavedSwapTransactionListModel>.updateList(
|
||||
private fun List<SavedSwapTransactionListModelInner>.updateList(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
transactions: List<SavedSwapTransactionModel>,
|
||||
): List<SavedSwapTransactionListModel> {
|
||||
): List<SavedSwapTransactionListModelInner> {
|
||||
return addOrReplace(
|
||||
item = SavedSwapTransactionListModel(
|
||||
userWalletId = userWalletId.stringValue,
|
||||
fromCryptoCurrencyId = fromCryptoCurrencyId.value,
|
||||
toCryptoCurrencyId = toCryptoCurrencyId.value,
|
||||
transactions = transactions,
|
||||
item = converter.default(
|
||||
userWalletId = userWalletId,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
tokenTransactions = transactions,
|
||||
),
|
||||
predicate = {
|
||||
it.checkId(
|
||||
checkUserWalletId = userWalletId,
|
||||
fromCurrencyId = fromCryptoCurrencyId,
|
||||
toCurrencyId = toCryptoCurrencyId,
|
||||
fromCurrencyId = fromCryptoCurrency.id,
|
||||
toCurrencyId = toCryptoCurrency.id,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
package com.tangem.feature.swap.converters
|
||||
|
||||
import com.tangem.data.tokens.utils.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.tokens.utils.UserTokensResponseFactory
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListModelInner
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class SavedSwapTransactionListConverter :
|
||||
Converter<SavedSwapTransactionListModel, SavedSwapTransactionListModelInner> {
|
||||
|
||||
private val responseCryptoCurrenciesFactory = ResponseCryptoCurrenciesFactory()
|
||||
private val userTokensResponseFactory = UserTokensResponseFactory()
|
||||
|
||||
override fun convert(value: SavedSwapTransactionListModel) = SavedSwapTransactionListModelInner(
|
||||
userWalletId = value.userWalletId,
|
||||
fromCryptoCurrencyId = value.fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = value.toCryptoCurrencyId,
|
||||
fromTokensResponse = userTokensResponseFactory.createResponseToken(
|
||||
value.fromCryptoCurrency,
|
||||
),
|
||||
toTokensResponse = userTokensResponseFactory.createResponseToken(
|
||||
value.toCryptoCurrency,
|
||||
),
|
||||
transactions = value.transactions,
|
||||
)
|
||||
|
||||
fun convertBack(
|
||||
value: SavedSwapTransactionListModelInner,
|
||||
scanResponse: ScanResponse,
|
||||
txStatuses: Map<String, ExchangeStatusModel>,
|
||||
): SavedSwapTransactionListModel? {
|
||||
val fromToken = value.fromTokensResponse
|
||||
val toToken = value.toTokensResponse
|
||||
return if (fromToken == null || toToken == null) {
|
||||
null
|
||||
} else {
|
||||
val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = fromToken,
|
||||
scanResponse = scanResponse,
|
||||
) ?: return null
|
||||
val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = toToken,
|
||||
scanResponse = scanResponse,
|
||||
) ?: return null
|
||||
|
||||
return SavedSwapTransactionListModel(
|
||||
transactions = value.transactions.map { tx ->
|
||||
tx.copy(status = txStatuses[tx.txId])
|
||||
},
|
||||
userWalletId = value.userWalletId,
|
||||
fromCryptoCurrencyId = value.fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = value.toCryptoCurrencyId,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun default(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
tokenTransactions: List<SavedSwapTransactionModel>,
|
||||
) = SavedSwapTransactionListModelInner(
|
||||
userWalletId = userWalletId.stringValue,
|
||||
fromCryptoCurrencyId = fromCryptoCurrency.id.value,
|
||||
toCryptoCurrencyId = toCryptoCurrency.id.value,
|
||||
fromTokensResponse = userTokensResponseFactory.createResponseToken(fromCryptoCurrency),
|
||||
toTokensResponse = userTokensResponseFactory.createResponseToken(toCryptoCurrency),
|
||||
transactions = tokenTransactions,
|
||||
)
|
||||
}
|
||||
|
|
@ -9,8 +9,8 @@ import com.tangem.datasource.di.NetworkMoshi
|
|||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.feature.swap.DefaultSwapTransactionRepository
|
||||
import com.tangem.feature.swap.DefaultSwapRepository
|
||||
import com.tangem.feature.swap.DefaultSwapTransactionRepository
|
||||
import com.tangem.feature.swap.converters.ErrorsDataConverter
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ dependencies {
|
|||
kapt(deps.hilt.kapt)
|
||||
|
||||
/** Domain */
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ dependencies {
|
|||
|
||||
/** Core modules */
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.datasource)
|
||||
|
||||
/** Other Libraries **/
|
||||
implementation(deps.kotlin.serialization)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,28 @@
|
|||
package com.tangem.feature.swap.domain.models.domain
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class SavedSwapTransactionListModel(
|
||||
val userWalletId: String,
|
||||
val fromCryptoCurrencyId: String,
|
||||
val toCryptoCurrencyId: String,
|
||||
val fromCryptoCurrency: CryptoCurrency,
|
||||
val toCryptoCurrency: CryptoCurrency,
|
||||
val transactions: List<SavedSwapTransactionModel>,
|
||||
)
|
||||
|
||||
/**
|
||||
* IMPORTANT !!!
|
||||
* This is internal model for storing swap tx. It should not be used outside.
|
||||
*/
|
||||
data class SavedSwapTransactionListModelInner(
|
||||
val userWalletId: String,
|
||||
val fromCryptoCurrencyId: String,
|
||||
val toCryptoCurrencyId: String,
|
||||
val fromTokensResponse: UserTokensResponse.Token? = null,
|
||||
val toTokensResponse: UserTokensResponse.Token? = null,
|
||||
val transactions: List<SavedSwapTransactionModel>,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -616,8 +616,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
) {
|
||||
swapTransactionRepository.storeTransaction(
|
||||
userWalletId = UserWalletId(userWalletManager.getWalletId()),
|
||||
fromCryptoCurrencyId = currencyToSend.currency.id,
|
||||
toCryptoCurrencyId = currencyToGet.currency.id,
|
||||
fromCryptoCurrency = currencyToSend.currency,
|
||||
toCryptoCurrency = currencyToGet.currency,
|
||||
transaction = SavedSwapTransactionModel(
|
||||
txId = swapDataModel.transaction.txId,
|
||||
provider = swapProvider,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.domain
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
|
||||
|
|
@ -11,20 +12,21 @@ interface SwapTransactionRepository {
|
|||
|
||||
suspend fun storeTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
transaction: SavedSwapTransactionModel,
|
||||
)
|
||||
|
||||
suspend fun getTransactions(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
scanResponse: ScanResponse,
|
||||
): Flow<List<SavedSwapTransactionListModel>?>
|
||||
|
||||
suspend fun removeTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
txId: String,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,12 @@ internal data class SwapTransactionsState(
|
|||
val hasFailed: Boolean,
|
||||
val statuses: ImmutableList<ExchangeStatusState>,
|
||||
val notification: ExchangeStatusNotifications? = null,
|
||||
val toCryptoCurrencyId: CryptoCurrency.ID,
|
||||
val toCryptoCurrency: CryptoCurrency,
|
||||
val toCryptoAmount: String,
|
||||
val toCryptoSymbol: String,
|
||||
val toFiatAmount: String,
|
||||
val toCurrencyIcon: TokenIconState,
|
||||
val fromCryptoCurrencyId: CryptoCurrency.ID,
|
||||
val fromCryptoCurrency: CryptoCurrency,
|
||||
val fromCryptoAmount: String,
|
||||
val fromCryptoSymbol: String,
|
||||
val fromFiatAmount: String,
|
||||
val fromCurrencyIcon: TokenIconState,
|
||||
val showProviderLink: Boolean,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.core.ui.utils.toDateFormat
|
|||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.models.analytics.TokenExchangeAnalyticsEvent
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatus
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
|
||||
|
|
@ -42,70 +42,70 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
|
||||
fun convert(
|
||||
savedTransactions: List<SavedSwapTransactionListModel>,
|
||||
cryptoStatusList: List<CryptoCurrencyStatus>,
|
||||
quotes: Set<Quote>,
|
||||
): PersistentList<SwapTransactionsState> {
|
||||
val result = mutableListOf<SwapTransactionsState>()
|
||||
|
||||
savedTransactions.forEach { swapCurrency ->
|
||||
val firstStatus = cryptoStatusList.first { it.currency.id.value == swapCurrency.fromCryptoCurrencyId }
|
||||
val secondStatus = cryptoStatusList.first { it.currency.id.value == swapCurrency.toCryptoCurrencyId }
|
||||
savedTransactions
|
||||
.forEach { swapCurrency ->
|
||||
val toCryptoCurrency = swapCurrency.toCryptoCurrency
|
||||
val fromCryptoCurrency = swapCurrency.fromCryptoCurrency
|
||||
|
||||
val (fromCurrency, toCurrency) = if (swapCurrency.fromCryptoCurrencyId == firstStatus.currency.id.value) {
|
||||
firstStatus to secondStatus
|
||||
} else {
|
||||
secondStatus to firstStatus
|
||||
swapCurrency.transactions.forEach { transaction ->
|
||||
val toAmount = transaction.toCryptoAmount
|
||||
val fromAmount = transaction.fromCryptoAmount
|
||||
val toFiatAmount = quotes.firstOrNull {
|
||||
it.rawCurrencyId == swapCurrency.fromCryptoCurrency.id.rawCurrencyId
|
||||
}?.fiatRate?.multiply(toAmount)
|
||||
val fromFiatAmount = quotes.firstOrNull {
|
||||
it.rawCurrencyId == swapCurrency.fromCryptoCurrency.id.rawCurrencyId
|
||||
}?.fiatRate?.multiply(fromAmount)
|
||||
val timestamp = transaction.timestamp
|
||||
val notifications =
|
||||
getNotification(transaction.status?.status, transaction.status?.txExternalUrl)
|
||||
val showProviderLink = getShowProviderLink(notifications, transaction.status)
|
||||
result.add(
|
||||
SwapTransactionsState(
|
||||
txId = transaction.txId,
|
||||
provider = transaction.provider,
|
||||
txUrl = transaction.status?.txExternalUrl,
|
||||
timestamp = TextReference.Str(
|
||||
"${timestamp.toDateFormat()}, ${timestamp.toTimeFormat()}",
|
||||
),
|
||||
fiatSymbol = appCurrency.symbol,
|
||||
statuses = getStatuses(transaction.status?.status),
|
||||
hasFailed = transaction.status?.status == ExchangeStatus.Failed,
|
||||
activeStatus = transaction.status?.status,
|
||||
notification = getNotification(
|
||||
transaction.status?.status,
|
||||
transaction.status?.txExternalUrl,
|
||||
),
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
toCryptoAmount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = toAmount,
|
||||
cryptoCurrency = toCryptoCurrency,
|
||||
),
|
||||
toFiatAmount = getFiatAmount(toFiatAmount),
|
||||
toCurrencyIcon = iconStateConverter.convert(toCryptoCurrency),
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
fromCryptoAmount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = fromAmount,
|
||||
cryptoCurrency = fromCryptoCurrency,
|
||||
),
|
||||
fromFiatAmount = getFiatAmount(fromFiatAmount),
|
||||
fromCurrencyIcon = iconStateConverter.convert(fromCryptoCurrency),
|
||||
showProviderLink = showProviderLink,
|
||||
onClick = { clickIntents.onSwapTransactionClick(transaction.txId) },
|
||||
onGoToProviderClick = { url ->
|
||||
analyticsEventsHandlerProvider().send(
|
||||
TokenExchangeAnalyticsEvent.GoToProviderStatus(cryptoCurrency.symbol),
|
||||
)
|
||||
clickIntents.onGoToProviderClick(url = url)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
swapCurrency.transactions.forEach { transaction ->
|
||||
val toAmount = transaction.toCryptoAmount
|
||||
val fromAmount = transaction.fromCryptoAmount
|
||||
val toFiatAmount = toAmount.multiply(toCurrency.value.fiatRate)
|
||||
val fromFiatAmount = fromAmount.multiply(fromCurrency.value.fiatRate)
|
||||
val timestamp = transaction.timestamp
|
||||
val notifications = getNotification(transaction.status?.status, transaction.status?.txExternalUrl)
|
||||
val showProviderLink = getShowProviderLink(notifications, transaction.status)
|
||||
result.add(
|
||||
SwapTransactionsState(
|
||||
txId = transaction.txId,
|
||||
provider = transaction.provider,
|
||||
txUrl = transaction.status?.txExternalUrl,
|
||||
timestamp = TextReference.Str("${timestamp.toDateFormat()}, ${timestamp.toTimeFormat()}"),
|
||||
fiatSymbol = appCurrency.symbol,
|
||||
statuses = getStatuses(transaction.status?.status),
|
||||
hasFailed = transaction.status?.status == ExchangeStatus.Failed,
|
||||
activeStatus = transaction.status?.status,
|
||||
notification = getNotification(
|
||||
transaction.status?.status,
|
||||
transaction.status?.txExternalUrl,
|
||||
),
|
||||
toCryptoCurrencyId = toCurrency.currency.id,
|
||||
toCryptoAmount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = toAmount,
|
||||
cryptoCurrency = toCurrency.currency,
|
||||
),
|
||||
toCryptoSymbol = toCurrency.currency.symbol,
|
||||
toFiatAmount = getFiatAmount(toFiatAmount),
|
||||
toCurrencyIcon = iconStateConverter.convert(toCurrency),
|
||||
fromCryptoCurrencyId = fromCurrency.currency.id,
|
||||
fromCryptoAmount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = fromAmount,
|
||||
cryptoCurrency = fromCurrency.currency,
|
||||
),
|
||||
fromCryptoSymbol = fromCurrency.currency.symbol,
|
||||
fromFiatAmount = getFiatAmount(fromFiatAmount),
|
||||
fromCurrencyIcon = iconStateConverter.convert(fromCurrency),
|
||||
showProviderLink = showProviderLink,
|
||||
onClick = { clickIntents.onSwapTransactionClick(transaction.txId) },
|
||||
onGoToProviderClick = { url ->
|
||||
analyticsEventsHandlerProvider().send(
|
||||
TokenExchangeAnalyticsEvent.GoToProviderStatus(cryptoCurrency.symbol),
|
||||
)
|
||||
clickIntents.onGoToProviderClick(url = url)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
return result.toPersistentList()
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getFiatAmount(toFiatAmount: BigDecimal): String {
|
||||
private fun getFiatAmount(toFiatAmount: BigDecimal?): String {
|
||||
return BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = toFiatAmount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ private fun ExchangeStatusBottomSheetContent(content: ExchangeStatusBottomSheetC
|
|||
fromTokenIconState = config.fromCurrencyIcon,
|
||||
toTokenIconState = config.toCurrencyIcon,
|
||||
fromCryptoAmount = TextReference.Str(config.fromCryptoAmount),
|
||||
fromCryptoSymbol = config.fromCryptoSymbol,
|
||||
fromCryptoSymbol = config.fromCryptoCurrency.symbol,
|
||||
toCryptoAmount = TextReference.Str(config.toCryptoAmount),
|
||||
toCryptoSymbol = config.toCryptoSymbol,
|
||||
toCryptoSymbol = config.toCryptoCurrency.symbol,
|
||||
fromFiatAmount = TextReference.Str(config.fromFiatAmount),
|
||||
toFiatAmount = TextReference.Str(config.toFiatAmount),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ internal fun LazyListScope.swapTransactionsItems(
|
|||
fromTokenIconState = item.fromCurrencyIcon,
|
||||
toTokenIconState = item.toCurrencyIcon,
|
||||
fromAmount = item.fromCryptoAmount,
|
||||
fromSymbol = item.fromCryptoSymbol,
|
||||
toSymbol = item.toCryptoSymbol,
|
||||
fromSymbol = item.fromCryptoCurrency.symbol,
|
||||
toSymbol = item.toCryptoCurrency.symbol,
|
||||
onClick = item.onClick,
|
||||
infoIconRes = iconRes,
|
||||
infoIconTint = tint,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.datasource.local.swaptx.ExchangeAnalyticsStatus
|
||||
import com.tangem.datasource.local.swaptx.SwapTransactionStatusStore
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.models.analytics.TokenExchangeAnalyticsEvent
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
|
|
@ -27,17 +26,18 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class ExchangeStatusFactory(
|
||||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val swapRepository: SwapRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusesSyncUseCase,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val clickIntents: TokenDetailsClickIntents,
|
||||
|
|
@ -57,14 +57,27 @@ internal class ExchangeStatusFactory(
|
|||
)
|
||||
}
|
||||
|
||||
suspend operator fun invoke() = combine(
|
||||
flow = swapTransactionRepository.getTransactions(userWalletId, cryptoCurrency.id),
|
||||
flow2 = getWalletCryptoCurrencies().conflate(),
|
||||
) { savedTransactions, cryptoCurrenciesStatusList ->
|
||||
getExchangeStatusState(
|
||||
savedTransactions = savedTransactions,
|
||||
cryptoCurrencyStatusList = cryptoCurrenciesStatusList,
|
||||
suspend operator fun invoke(): Flow<PersistentList<SwapTransactionsState>> {
|
||||
val selectedWallet = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { return emptyFlow() },
|
||||
ifRight = { it },
|
||||
)
|
||||
return swapTransactionRepository.getTransactions(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
scanResponse = selectedWallet.scanResponse,
|
||||
).conflate()
|
||||
.map { savedTransactions ->
|
||||
val quotes = savedTransactions
|
||||
?.flatMap { setOf(it.fromCryptoCurrency.id, it.toCryptoCurrency.id) }
|
||||
?.let { quotesRepository.getQuotesSync(it.toSet(), true) }
|
||||
?: emptySet()
|
||||
|
||||
getExchangeStatusState(
|
||||
savedTransactions = savedTransactions,
|
||||
quotes = quotes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun removeTransactionOnBottomSheetClosed(): TokenDetailsState {
|
||||
|
|
@ -75,8 +88,8 @@ internal class ExchangeStatusFactory(
|
|||
return if (selectedTx.activeStatus.isTerminal()) {
|
||||
swapTransactionRepository.removeTransaction(
|
||||
userWalletId = userWalletId,
|
||||
fromCryptoCurrencyId = selectedTx.fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = selectedTx.toCryptoCurrencyId,
|
||||
fromCryptoCurrency = selectedTx.fromCryptoCurrency,
|
||||
toCryptoCurrency = selectedTx.toCryptoCurrency,
|
||||
txId = selectedTx.txId,
|
||||
)
|
||||
val filteredTxs = state.swapTxs
|
||||
|
|
@ -88,19 +101,6 @@ internal class ExchangeStatusFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getWalletCryptoCurrencies() = flow {
|
||||
val selectedWallet = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { null },
|
||||
ifRight = { it },
|
||||
)
|
||||
requireNotNull(selectedWallet) { "No selected wallet" }
|
||||
|
||||
val cryptoCurrenciesList = getMultiCryptoCurrencyStatusUseCase(selectedWallet.walletId)
|
||||
.getOrElse { emptyList() }
|
||||
|
||||
emit(cryptoCurrenciesList)
|
||||
}
|
||||
|
||||
suspend fun updateSwapTxStatuses(swapTxList: PersistentList<SwapTransactionsState>) = withContext(dispatchers.io) {
|
||||
swapTxList.map { tx ->
|
||||
async {
|
||||
|
|
@ -144,15 +144,15 @@ internal class ExchangeStatusFactory(
|
|||
|
||||
private fun getExchangeStatusState(
|
||||
savedTransactions: List<SavedSwapTransactionListModel>?,
|
||||
cryptoCurrencyStatusList: List<CryptoCurrencyStatus>,
|
||||
quotes: Set<Quote>,
|
||||
): PersistentList<SwapTransactionsState> {
|
||||
if (savedTransactions == null || cryptoCurrencyStatusList.isEmpty()) {
|
||||
if (savedTransactions == null) {
|
||||
return persistentListOf()
|
||||
}
|
||||
|
||||
return swapTransactionsStateConverter.convert(
|
||||
savedTransactions = savedTransactions,
|
||||
cryptoStatusList = cryptoCurrencyStatusList,
|
||||
quotes = quotes,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.tangem.domain.tokens.models.analytics.TokenExchangeAnalyticsEvent
|
|||
import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent
|
||||
import com.tangem.domain.tokens.models.analytics.TokenScreenAnalyticsEvent
|
||||
import com.tangem.domain.tokens.models.analytics.TokenSwapPromoAnalyticsEvent
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
|
|
@ -76,10 +77,10 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusesSyncUseCase,
|
||||
private val shouldShowSwapPromoTokenUseCase: ShouldShowSwapPromoTokenUseCase,
|
||||
private val swapRepository: SwapRepository,
|
||||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
|
|
@ -118,8 +119,8 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
ExchangeStatusFactory(
|
||||
swapTransactionRepository = swapTransactionRepository,
|
||||
swapRepository = swapRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
|
||||
getMultiCryptoCurrencyStatusUseCase = getMultiCryptoCurrencyStatusUseCase,
|
||||
swapTransactionStatusStore = swapTransactionStatusStore,
|
||||
dispatchers = dispatchers,
|
||||
clickIntents = this,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue