Updated on 2026-08-14
This commit is contained in:
parent
4c51193221
commit
c8a181c829
13 changed files with 135 additions and 73 deletions
|
|
@ -13,7 +13,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
|
|||
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.getObjectMapSync
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -24,9 +24,8 @@ import com.tangem.domain.swap.models.SwapTransactionModel
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class DefaultSwapTransactionRepository(
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
|
|
@ -95,36 +94,34 @@ internal class DefaultSwapTransactionRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getTransactions(
|
||||
override fun getTransactions(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
): Flow<List<SwapTransactionListModel>?> {
|
||||
return withContext(dispatchers.io) {
|
||||
val txStatuses = appPreferencesStore.getObjectMapSync<SwapStatusDTO>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||
)
|
||||
appPreferencesStore.getObjectList<SwapTransactionListDTO>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
).map { savedTransactions ->
|
||||
val currencyTxs = savedTransactions
|
||||
?.filter {
|
||||
it.userWalletId == userWallet.walletId.stringValue &&
|
||||
(
|
||||
it.toCryptoCurrencyId == cryptoCurrencyId.value ||
|
||||
it.fromCryptoCurrencyId == cryptoCurrencyId.value
|
||||
)
|
||||
}
|
||||
): Flow<List<SwapTransactionListModel>?> = combine(
|
||||
flow = appPreferencesStore.getObjectList<SwapTransactionListDTO>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
|
||||
),
|
||||
flow2 = appPreferencesStore.getObjectMap<SwapStatusDTO>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||
),
|
||||
) { savedTransactions, txStatuses ->
|
||||
val currencyTxs = savedTransactions
|
||||
?.filter {
|
||||
it.userWalletId == userWallet.walletId.stringValue &&
|
||||
(
|
||||
it.toCryptoCurrencyId == cryptoCurrencyId.value ||
|
||||
it.fromCryptoCurrencyId == cryptoCurrencyId.value
|
||||
)
|
||||
}
|
||||
|
||||
currencyTxs?.mapNotNull {
|
||||
listConverter.convertBack(
|
||||
value = it,
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
}.flowOn(dispatchers.io)
|
||||
currencyTxs?.mapNotNull {
|
||||
listConverter.convertBack(
|
||||
value = it,
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
}
|
||||
}.flowOn(dispatchers.default)
|
||||
|
||||
override suspend fun removeTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -188,7 +185,7 @@ internal class DefaultSwapTransactionRepository(
|
|||
)
|
||||
|
||||
val updatesMap = savedMap.toMutableMap()
|
||||
updatesMap[txId] = savedStatusConverter.convertBack(
|
||||
updatesMap[txId] = savedStatusConverter.convert(
|
||||
status.copy(
|
||||
refundTokensResponse = refundTokenCurrency?.let {
|
||||
userTokensResponseFactory.createResponseToken(refundTokenCurrency)
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import com.tangem.domain.swap.models.SwapStatus
|
|||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class SavedSwapStatusConverter : TwoWayConverter<SwapStatusDTO, SwapStatusModel> {
|
||||
internal class SavedSwapStatusConverter : TwoWayConverter<SwapStatusModel, SwapStatusDTO> {
|
||||
|
||||
override fun convert(value: SwapStatusDTO) = SwapStatusModel(
|
||||
override fun convertBack(value: SwapStatusDTO) = SwapStatusModel(
|
||||
providerId = value.providerId,
|
||||
status = SwapStatus.entries.firstOrNull {
|
||||
it.name.lowercase() == value.status?.name?.lowercase()
|
||||
|
|
@ -22,7 +22,7 @@ internal class SavedSwapStatusConverter : TwoWayConverter<SwapStatusDTO, SwapSta
|
|||
averageDuration = value.averageDuration,
|
||||
)
|
||||
|
||||
override fun convertBack(value: SwapStatusModel) = SwapStatusDTO(
|
||||
override fun convert(value: SwapStatusModel) = SwapStatusDTO(
|
||||
providerId = value.providerId,
|
||||
status = SavedSwapStatus.entries.firstOrNull {
|
||||
it.name.lowercase() == value.status?.name?.lowercase()
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package com.tangem.data.swap.converter.transaction
|
|||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.swap.models.SwapStatusDTO
|
||||
import com.tangem.data.swap.models.SwapTransactionDTO
|
||||
import com.tangem.data.swap.models.SwapTxTypeDTO
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.swap.models.SwapTxType
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class SavedSwapTransactionConverter(
|
||||
|
|
@ -21,7 +23,10 @@ internal class SavedSwapTransactionConverter(
|
|||
fromCryptoAmount = value.fromCryptoAmount,
|
||||
toCryptoAmount = value.toCryptoAmount,
|
||||
provider = value.provider,
|
||||
status = value.status,
|
||||
status = value.status?.let(statusConverter::convert),
|
||||
swapTxType = SwapTxTypeDTO.entries.firstOrNull {
|
||||
it.name.lowercase() == value.swapTxType?.name?.lowercase()
|
||||
},
|
||||
)
|
||||
|
||||
override fun convertBack(value: SwapTransactionDTO) = SwapTransactionModel(
|
||||
|
|
@ -30,7 +35,10 @@ internal class SavedSwapTransactionConverter(
|
|||
fromCryptoAmount = value.fromCryptoAmount,
|
||||
toCryptoAmount = value.toCryptoAmount,
|
||||
provider = value.provider,
|
||||
status = value.status,
|
||||
status = value.status?.let(statusConverter::convertBack),
|
||||
swapTxType = SwapTxType.entries.firstOrNull {
|
||||
it.name.lowercase() == value.swapTxType?.name?.lowercase()
|
||||
},
|
||||
)
|
||||
|
||||
fun convertBack(
|
||||
|
|
@ -53,7 +61,10 @@ internal class SavedSwapTransactionConverter(
|
|||
fromCryptoAmount = value.fromCryptoAmount,
|
||||
toCryptoAmount = value.toCryptoAmount,
|
||||
provider = value.provider,
|
||||
status = statusWithRefundCurrency?.let(statusConverter::convert),
|
||||
status = statusWithRefundCurrency?.let(statusConverter::convertBack),
|
||||
swapTxType = SwapTxType.entries.firstOrNull {
|
||||
it.name.lowercase() == value.swapTxType?.name?.lowercase()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
@ -36,5 +35,7 @@ internal data class SwapTransactionDTO(
|
|||
@Json(name = "provider")
|
||||
val provider: ExpressProvider,
|
||||
@Json(name = "status")
|
||||
val status: SwapStatusModel? = null,
|
||||
val status: SwapStatusDTO? = null,
|
||||
@Json(name = "swapTxType")
|
||||
val swapTxType: SwapTxTypeDTO? = SwapTxTypeDTO.Swap,
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.data.swap.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
internal enum class SwapTxTypeDTO {
|
||||
@Json(name = "Swap")
|
||||
Swap,
|
||||
|
||||
@Json(name = "SendWithSwap")
|
||||
SendWithSwap,
|
||||
}
|
||||
|
|
@ -26,4 +26,5 @@ data class SwapTransactionModel(
|
|||
val toCryptoAmount: BigDecimal,
|
||||
val provider: ExpressProvider,
|
||||
val status: SwapStatusModel? = null,
|
||||
val swapTxType: SwapTxType? = SwapTxType.Swap,
|
||||
)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.domain.swap.models
|
||||
|
||||
enum class SwapTxType {
|
||||
Swap,
|
||||
SendWithSwap,
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.domain.swap
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.domain.swap.models.SwapTransactionListModel
|
||||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
|
|
@ -34,7 +34,7 @@ interface SwapTransactionRepository {
|
|||
* @param userWallet selected user wallet
|
||||
* @param cryptoCurrencyId transactions for specific crypto currency
|
||||
*/
|
||||
suspend fun getTransactions(
|
||||
fun getTransactions(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
): Flow<List<SwapTransactionListModel>?>
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.SwapTransactionRepository
|
||||
import com.tangem.domain.swap.models.SwapDataTransactionModel
|
||||
import com.tangem.domain.swap.models.SwapStatus
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.swap.models.*
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class SwapTransactionSentUseCase(
|
||||
|
|
@ -28,15 +25,8 @@ class SwapTransactionSentUseCase(
|
|||
provider: ExpressProvider,
|
||||
txHash: String,
|
||||
timestamp: Long,
|
||||
swapTxType: SwapTxType,
|
||||
) = Either.catch {
|
||||
swapRepositoryV2.swapTransactionSent(
|
||||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
toAddress = swapDataTransactionModel.txTo,
|
||||
txId = swapDataTransactionModel.txId,
|
||||
txHash = txHash,
|
||||
txExtraId = swapDataTransactionModel.txExtraId,
|
||||
)
|
||||
if (provider.type.shouldStoreSwapTransaction()) {
|
||||
swapTransactionRepository.storeTransaction(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
@ -56,12 +46,22 @@ class SwapTransactionSentUseCase(
|
|||
txExternalId = (swapDataTransactionModel as? SwapDataTransactionModel.CEX)?.externalTxId,
|
||||
averageDuration = null,
|
||||
),
|
||||
swapTxType = swapTxType,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
swapTransactionRepository.storeLastSwappedCryptoCurrencyId(
|
||||
userWalletId = userWallet.walletId,
|
||||
cryptoCurrencyId = toCryptoCurrencyStatus.currency.id,
|
||||
)
|
||||
swapRepositoryV2.swapTransactionSent(
|
||||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
toAddress = swapDataTransactionModel.txTo,
|
||||
txId = swapDataTransactionModel.txId,
|
||||
txHash = txHash,
|
||||
txExtraId = swapDataTransactionModel.txExtraId,
|
||||
)
|
||||
}.mapLeft(swapErrorResolver::resolve)
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.swap.models.SwapDataTransactionModel
|
||||
import com.tangem.domain.swap.models.SwapTxType
|
||||
import com.tangem.domain.swap.usecase.GetSwapDataUseCase
|
||||
import com.tangem.domain.swap.usecase.SwapTransactionSentUseCase
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
|
|
@ -158,6 +159,7 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
provider = provider,
|
||||
txHash = txHash,
|
||||
timestamp = timestamp,
|
||||
swapTxType = SwapTxType.SendWithSwap,
|
||||
)
|
||||
onSendSuccess(txHash, timestamp, swapData)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -92,21 +92,37 @@ internal class DefaultSwapTransactionRepository(
|
|||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||
),
|
||||
) { savedTransactions, txStatuses ->
|
||||
val currencyTxs = savedTransactions?.filter {
|
||||
it.userWalletId == userWallet.walletId.stringValue &&
|
||||
(
|
||||
it.toCryptoCurrencyId == cryptoCurrencyId.value ||
|
||||
it.fromCryptoCurrencyId == cryptoCurrencyId.value
|
||||
)
|
||||
|
||||
val currencyToTxs = savedTransactions?.filter {
|
||||
val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
|
||||
val toCurrency = it.toCryptoCurrencyId == cryptoCurrencyId.value
|
||||
isUserWallet && toCurrency
|
||||
}
|
||||
|
||||
currencyTxs?.mapNotNull {
|
||||
val currencyFromTxs = savedTransactions?.filter {
|
||||
val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
|
||||
val fromCurrency = it.fromCryptoCurrencyId == cryptoCurrencyId.value
|
||||
isUserWallet && fromCurrency
|
||||
}
|
||||
|
||||
val toTxs = currencyToTxs?.mapNotNull {
|
||||
converter.convertBack(
|
||||
value = it,
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
onFilter = { it.swapTxTypeDTO == SwapTxTypeDTO.Swap },
|
||||
)
|
||||
}.orEmpty()
|
||||
|
||||
val fromTxs = currencyFromTxs?.mapNotNull {
|
||||
converter.convertBack(
|
||||
value = it,
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
}.orEmpty()
|
||||
|
||||
fromTxs + toTxs
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ internal class SavedSwapTransactionListConverter(
|
|||
value: SavedSwapTransactionListModelInner,
|
||||
userWallet: UserWallet,
|
||||
txStatuses: Map<String, ExchangeStatusModel>,
|
||||
onFilter: (SavedSwapTransactionModel) -> Boolean = { true },
|
||||
): SavedSwapTransactionListModel? {
|
||||
val fromToken = value.fromTokensResponse
|
||||
val toToken = value.toTokensResponse
|
||||
|
|
@ -50,17 +51,19 @@ internal class SavedSwapTransactionListConverter(
|
|||
) ?: return null
|
||||
|
||||
return SavedSwapTransactionListModel(
|
||||
transactions = value.transactions.map { tx ->
|
||||
val status = txStatuses[tx.txId]
|
||||
val refundCurrency = status?.refundTokensResponse?.let { id ->
|
||||
responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = id,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
|
||||
tx.copy(status = statusWithRefundCurrency)
|
||||
},
|
||||
transactions = value.transactions
|
||||
.filter(onFilter)
|
||||
.map { tx ->
|
||||
val status = txStatuses[tx.txId]
|
||||
val refundCurrency = status?.refundTokensResponse?.let { id ->
|
||||
responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = id,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
|
||||
tx.copy(status = statusWithRefundCurrency)
|
||||
},
|
||||
userWalletId = value.userWalletId,
|
||||
fromCryptoCurrencyId = value.fromCryptoCurrencyId,
|
||||
toCryptoCurrencyId = value.toCryptoCurrencyId,
|
||||
|
|
|
|||
|
|
@ -50,4 +50,16 @@ data class SavedSwapTransactionModel(
|
|||
val provider: SwapProvider,
|
||||
@Json(name = "status")
|
||||
val status: ExchangeStatusModel? = null,
|
||||
)
|
||||
@Json(name = "swapTxType")
|
||||
val swapTxTypeDTO: SwapTxTypeDTO? = SwapTxTypeDTO.Swap,
|
||||
)
|
||||
|
||||
// TODO refactor to use separate models to store
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class SwapTxTypeDTO {
|
||||
@Json(name = "Swap")
|
||||
Swap,
|
||||
|
||||
@Json(name = "SendWithSwap")
|
||||
SendWithSwap,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue