Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-21 18:54:47 +05:00
parent 81cce1254d
commit 879c8d603b
19 changed files with 566 additions and 415 deletions

View file

@ -23,6 +23,7 @@ import com.tangem.core.ui.R
import com.tangem.core.ui.components.CircleShimmer
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.components.transactions.state.TransactionState.Content.*
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@ -116,11 +117,11 @@ private fun Icon(state: TransactionState, modifier: Modifier = Modifier) {
modifier = modifier
.size(TangemTheme.dimens.size40)
.background(
color = when (state) {
is TransactionState.ProcessedTransactionContent -> {
color = when (state.status) {
is Status.Unconfirmed -> {
TangemTheme.colors.icon.attention.copy(alpha = 0.1f)
}
is TransactionState.CompletedTransactionContent -> {
is Status.Confirmed, Status.Failed -> {
TangemTheme.colors.background.secondary
}
},
@ -130,30 +131,20 @@ private fun Icon(state: TransactionState, modifier: Modifier = Modifier) {
Icon(
painter = painterResource(
id = when (state) {
is TransactionState.Sending,
is TransactionState.Send,
-> R.drawable.ic_arrow_up_24
is TransactionState.Receiving,
is TransactionState.Receive,
-> R.drawable.ic_arrow_down_24
is TransactionState.Approving,
is TransactionState.Approved,
-> R.drawable.ic_doc_24
is TransactionState.Swapping,
is TransactionState.Swapped,
-> R.drawable.ic_exchange_vertical_24
is TransactionState.Send -> R.drawable.ic_arrow_up_24
is TransactionState.Receive -> R.drawable.ic_arrow_down_24
is TransactionState.Approve -> R.drawable.ic_doc_24
is TransactionState.Swap -> R.drawable.ic_exchange_vertical_24
is TransactionState.Custom -> R.drawable.ic_exchange_vertical_24
},
),
contentDescription = null,
modifier = Modifier
.size(TangemTheme.dimens.size20)
.align(Alignment.Center),
tint = when (state) {
is TransactionState.ProcessedTransactionContent -> TangemTheme.colors.icon.attention
is TransactionState.CompletedTransactionContent -> TangemTheme.colors.icon.informative
tint = when (state.status) {
Status.Confirmed, Status.Failed -> TangemTheme.colors.icon.informative
Status.Unconfirmed -> TangemTheme.colors.icon.attention
},
)
}
@ -179,43 +170,29 @@ private fun Icon(state: TransactionState, modifier: Modifier = Modifier) {
@Composable
private fun Title(state: TransactionState, modifier: Modifier = Modifier) {
when (state) {
is TransactionState.ProcessedTransactionContent -> {
is TransactionState.Content -> {
Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6)) {
Text(
text = stringResource(
id = when (state) {
is TransactionState.Sending -> R.string.common_transfer
is TransactionState.Receiving -> R.string.common_transfer
is TransactionState.Approving -> R.string.common_approval
is TransactionState.Swapping -> R.string.common_swap
},
),
text = when (state) {
is TransactionState.Approve -> stringResource(R.string.common_approval)
is TransactionState.Receive -> stringResource(R.string.common_transfer)
is TransactionState.Send -> stringResource(R.string.common_transfer)
is TransactionState.Swap -> stringResource(R.string.common_swap)
is TransactionState.Custom -> state.title.resolveReference()
},
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
Image(
modifier = Modifier.align(Alignment.CenterVertically),
painter = painterResource(id = R.drawable.img_loader_15),
contentDescription = null,
)
if (state.status is Status.Unconfirmed) {
Image(
modifier = Modifier.align(Alignment.CenterVertically),
painter = painterResource(id = R.drawable.img_loader_15),
contentDescription = null,
)
}
}
}
is TransactionState.CompletedTransactionContent -> {
Text(
text = stringResource(
id = when (state) {
is TransactionState.Send -> R.string.common_transfer
is TransactionState.Receive -> R.string.common_transfer
is TransactionState.Approved -> R.string.common_approval
is TransactionState.Swapped -> R.string.common_swap
},
),
modifier = modifier,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
}
is TransactionState.Loading -> {
RectangleShimmer(
modifier = modifier.size(width = TangemTheme.dimens.size70, height = TangemTheme.dimens.size12),
@ -235,26 +212,28 @@ private fun Subtitle(state: TransactionState, modifier: Modifier = Modifier) {
is TransactionState.Content -> {
Text(
text = when (state) {
is TransactionState.Sending,
is TransactionState.Send,
-> stringResource(
is TransactionState.Send -> stringResource(
id = R.string.transaction_history_transaction_to_address,
state.address.resolveReference(),
)
is TransactionState.Receiving,
is TransactionState.Receive,
is TransactionState.Approving,
is TransactionState.Approved,
is TransactionState.Approve,
-> stringResource(
id = R.string.transaction_history_transaction_from_address,
state.address.resolveReference(),
)
is TransactionState.Swapping,
is TransactionState.Swapped,
-> stringResource(
is TransactionState.Swap -> stringResource(
id = R.string.transaction_history_contract_address,
state.address.resolveReference(),
)
is TransactionState.Custom -> stringResource(
id = if (state.isIncoming) {
R.string.transaction_history_transaction_from_address
} else {
R.string.transaction_history_transaction_to_address
},
state.subtitle.resolveReference(),
)
},
modifier = modifier,
textAlign = TextAlign.Start,
@ -357,53 +336,53 @@ private fun Preview_TransactionItem_DarkTheme(
private class TransactionItemStateProvider : CollectionPreviewParameterProvider<TransactionState>(
collection = listOf(
TransactionState.Sending(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "-0.500913 BTC",
timestamp = "8:41",
),
TransactionState.Receiving(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
),
TransactionState.Approving(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
),
TransactionState.Swapping(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
),
TransactionState.Send(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "-0.500913 BTC",
timestamp = "8:41",
status = Status.Confirmed,
),
TransactionState.Receive(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
status = Status.Unconfirmed,
),
TransactionState.Approved(
TransactionState.Approve(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
status = Status.Failed,
),
TransactionState.Swapped(
TransactionState.Swap(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
status = Status.Unconfirmed,
),
TransactionState.Custom(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
status = Status.Confirmed,
title = TextReference.Str("Submit"),
subtitle = TextReference.Str("33BddS...ga2B"),
isIncoming = true,
),
TransactionState.Custom(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "+0.500913 BTC",
timestamp = "8:41",
status = Status.Confirmed,
title = TextReference.Str("Submit"),
subtitle = TextReference.Str("33BddS...ga2B"),
isIncoming = false,
),
TransactionState.Loading(txHash = UUID.randomUUID().toString()),
),

View file

@ -15,127 +15,41 @@ sealed interface TransactionState {
/**
* Content state
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
* @property status transaction status
*/
sealed class Content(
override val txHash: String,
open val address: TextReference,
open val amount: String,
open val timestamp: String,
) : TransactionState {
sealed class Content : TransactionState {
abstract val address: TextReference
abstract val amount: String
abstract val timestamp: String
abstract val status: Status
fun copySealed(
txHash: String = this.txHash,
address: TextReference = this.address,
amount: String = this.amount,
timestamp: String = this.timestamp,
status: Status = this.status,
): Content {
return when (this) {
is Approved -> copy(txHash, address, amount, timestamp)
is Receive -> copy(txHash, address, amount, timestamp)
is Send -> copy(txHash, address, amount, timestamp)
is Swapped -> copy(txHash, address, amount, timestamp)
is Approving -> copy(txHash, address, amount, timestamp)
is Receiving -> copy(txHash, address, amount, timestamp)
is Sending -> copy(txHash, address, amount, timestamp)
is Swapping -> copy(txHash, address, amount, timestamp)
is Approve -> copy(txHash, address, amount, timestamp, status)
is Receive -> copy(txHash, address, amount, timestamp, status)
is Send -> copy(txHash, address, amount, timestamp, status)
is Swap -> copy(txHash, address, amount, timestamp, status)
is Custom -> copy(txHash, address, amount, timestamp, status)
}
}
sealed class Status {
object Failed : Status()
object Confirmed : Status()
object Unconfirmed : Status()
}
}
/**
* Content state for processed transaction
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
sealed class ProcessedTransactionContent(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : Content(txHash, address, amount, timestamp)
/**
* Content state for completed transaction
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
sealed class CompletedTransactionContent(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : Content(txHash, address, amount, timestamp)
/**
* Processed sending transaction state
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
data class Sending(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : ProcessedTransactionContent(txHash, address, amount, timestamp)
/**
* Processed receiving transaction state
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
data class Receiving(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : ProcessedTransactionContent(txHash, address, amount, timestamp)
/**
* Processed approving transaction state
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
data class Approving(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : ProcessedTransactionContent(txHash, address, amount, timestamp)
/**
* Processed swapping transaction state
*
* @property txHash transaction hash
* @property address address
* @property amount amount
* @property timestamp timestamp
*/
data class Swapping(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : ProcessedTransactionContent(txHash, address, amount, timestamp)
/**
* Completed sending transaction state
*
@ -149,7 +63,8 @@ sealed interface TransactionState {
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : CompletedTransactionContent(txHash, address, amount, timestamp)
override val status: Status,
) : Content()
/**
* Completed receiving transaction state
@ -164,7 +79,8 @@ sealed interface TransactionState {
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : CompletedTransactionContent(txHash, address, amount, timestamp)
override val status: Status,
) : Content()
/**
* Completed approving transaction state
@ -174,12 +90,13 @@ sealed interface TransactionState {
* @property amount amount
* @property timestamp timestamp
*/
data class Approved(
data class Approve(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : CompletedTransactionContent(txHash, address, amount, timestamp)
override val status: Status,
) : Content()
/**
* Completed swapping transaction state
@ -189,12 +106,24 @@ sealed interface TransactionState {
* @property amount amount
* @property timestamp timestamp
*/
data class Swapped(
data class Swap(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
) : CompletedTransactionContent(txHash, address, amount, timestamp)
override val status: Status,
) : Content()
data class Custom(
override val txHash: String,
override val address: TextReference,
override val amount: String,
override val timestamp: String,
override val status: Status,
val title: TextReference,
val subtitle: TextReference,
val isIncoming: Boolean,
) : Content()
/**
* Loading state

View file

@ -5,6 +5,7 @@ import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.tangem.data.txhistory.repository.paging.TxHistoryPagingSource
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryState
@ -33,7 +34,7 @@ class DefaultTxHistoryRepository(
}
}
override fun getTxHistoryItems(network: Network, pageSize: Int): Flow<PagingData<TxHistoryItem>> {
override fun getTxHistoryItems(currency: CryptoCurrency, pageSize: Int): Flow<PagingData<TxHistoryItem>> {
val userWallet = getUserWallet()
return Pager(
config = PagingConfig(
@ -44,7 +45,7 @@ class DefaultTxHistoryRepository(
loadPage = { page: Int, pageSize: Int ->
walletManagersFacade.getTxHistoryItems(
userWalletId = userWallet.walletId,
network = network,
currency = currency,
page = page,
pageSize = pageSize,
)

View file

@ -4,6 +4,7 @@ import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.address.Address
import com.tangem.blockchain.common.txhistory.TransactionHistoryRequest
import com.tangem.blockchain.extensions.Result
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.datasource.config.ConfigManager
@ -89,16 +90,16 @@ class DefaultWalletManagersFacade(
override suspend fun getTxHistoryItems(
userWalletId: UserWalletId,
network: Network,
currency: CryptoCurrency,
page: Int,
pageSize: Int,
): PaginationWrapper<TxHistoryItem> {
val userWallet = getUserWallet(userWalletId)
val blockchain = Blockchain.fromId(network.id.value)
val blockchain = Blockchain.fromId(currency.network.id.value)
val walletManager = getOrCreateWalletManager(
userWallet = userWallet,
blockchain = blockchain,
derivationPath = network.derivationPath.value,
derivationPath = currency.network.derivationPath.value,
)
requireNotNull(walletManager) {
@ -106,9 +107,14 @@ class DefaultWalletManagersFacade(
}
val itemsResult = walletManager.getTransactionsHistory(
address = walletManager.wallet.address,
page = page,
pageSize = pageSize,
request = TransactionHistoryRequest(
address = walletManager.wallet.address,
page = TransactionHistoryRequest.Page(number = page, size = pageSize),
filterType = when (currency) {
is CryptoCurrency.Coin -> TransactionHistoryRequest.FilterType.Coin
is CryptoCurrency.Token -> TransactionHistoryRequest.FilterType.Contract(currency.contractAddress)
},
),
)
return when (itemsResult) {

View file

@ -57,13 +57,13 @@ interface WalletManagersFacade {
* Returns transaction history items wrapped to pagination
*
* @param userWalletId The ID of the user's wallet.
* @param network The network.
* @param currency currency.
* @param page Pagination page.
* @param pageSize Pagination size.
*/
suspend fun getTxHistoryItems(
userWalletId: UserWalletId,
network: Network,
currency: CryptoCurrency,
page: Int,
pageSize: Int,
): PaginationWrapper<TxHistoryItem>

View file

@ -1,6 +1,5 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.TransactionStatus
import com.tangem.blockchain.common.txhistory.TransactionHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.utils.converter.Converter
@ -13,11 +12,20 @@ internal class SdkTransactionHistoryItemConverter : Converter<SdkTransactionHist
timestampInMillis = value.timestamp,
direction = value.direction.toDomain(),
status = when (value.status) {
TransactionStatus.Confirmed -> TxHistoryItem.TxStatus.Confirmed
TransactionStatus.Unconfirmed -> TxHistoryItem.TxStatus.Unconfirmed
TransactionHistoryItem.TransactionStatus.Confirmed -> TxHistoryItem.TransactionStatus.Confirmed
TransactionHistoryItem.TransactionStatus.Failed -> TxHistoryItem.TransactionStatus.Failed
TransactionHistoryItem.TransactionStatus.Unconfirmed -> TxHistoryItem.TransactionStatus.Unconfirmed
},
type = when (value.type) {
type = when (val type = value.type) {
TransactionHistoryItem.TransactionType.Transfer -> TxHistoryItem.TransactionType.Transfer
TransactionHistoryItem.TransactionType.Approve -> TxHistoryItem.TransactionType.Approve
is TransactionHistoryItem.TransactionType.Custom -> TxHistoryItem.TransactionType.Custom(type.id)
TransactionHistoryItem.TransactionType.Deposit -> TxHistoryItem.TransactionType.Deposit
TransactionHistoryItem.TransactionType.Submit -> TxHistoryItem.TransactionType.Submit
TransactionHistoryItem.TransactionType.Supply -> TxHistoryItem.TransactionType.Supply
TransactionHistoryItem.TransactionType.Swap -> TxHistoryItem.TransactionType.Swap
TransactionHistoryItem.TransactionType.Unoswap -> TxHistoryItem.TransactionType.Unoswap
TransactionHistoryItem.TransactionType.Withdraw -> TxHistoryItem.TransactionType.Withdraw
},
amount = requireNotNull(value.amount.value) { "Transaction amount value must not be null" },
)

View file

@ -130,8 +130,8 @@ internal class UpdateWalletManagerResultFactory {
timestampInMillis = TimeUnit.SECONDS.toMillis(millis),
direction = direction,
status = when (data.status) {
TransactionStatus.Confirmed -> TxHistoryItem.TxStatus.Confirmed
TransactionStatus.Unconfirmed -> TxHistoryItem.TxStatus.Unconfirmed
TransactionStatus.Confirmed -> TxHistoryItem.TransactionStatus.Confirmed
TransactionStatus.Unconfirmed -> TxHistoryItem.TransactionStatus.Unconfirmed
},
type = TxHistoryItem.TransactionType.Transfer,
amount = amount,

View file

@ -6,7 +6,7 @@ data class TxHistoryItem(
val txHash: String,
val timestampInMillis: Long,
val direction: TransactionDirection,
val status: TxStatus,
val status: TransactionStatus,
val type: TransactionType,
val amount: BigDecimal,
) {
@ -20,9 +20,21 @@ data class TxHistoryItem(
sealed interface TransactionType {
object Transfer : TransactionType
object Submit : TransactionType
object Approve : TransactionType
object Supply : TransactionType
object Withdraw : TransactionType
object Deposit : TransactionType
object Swap : TransactionType
object Unoswap : TransactionType
data class Custom(val id: String) : TransactionType
}
enum class TxStatus { Confirmed, Unconfirmed }
sealed class TransactionStatus {
object Failed : TransactionStatus()
object Unconfirmed : TransactionStatus()
object Confirmed : TransactionStatus()
}
sealed class Address {
data class Single(val rawAddress: String) : Address()

View file

@ -1,6 +1,7 @@
package com.tangem.domain.txhistory.repository
import androidx.paging.PagingData
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryListError
@ -13,5 +14,5 @@ interface TxHistoryRepository {
suspend fun getTxHistoryItemsCount(network: Network): Int
@Throws(TxHistoryListError::class)
fun getTxHistoryItems(network: Network, pageSize: Int): Flow<PagingData<TxHistoryItem>>
fun getTxHistoryItems(currency: CryptoCurrency, pageSize: Int): Flow<PagingData<TxHistoryItem>>
}

View file

@ -3,7 +3,7 @@ package com.tangem.domain.txhistory.usecase
import androidx.paging.PagingData
import arrow.core.Either
import arrow.core.raise.either
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryListError
import com.tangem.domain.txhistory.repository.TxHistoryRepository
@ -15,12 +15,12 @@ private const val DEFAULT_PAGE_SIZE = 20
class GetTxHistoryItemsUseCase(private val repository: TxHistoryRepository) {
operator fun invoke(
network: Network,
currency: CryptoCurrency,
pageSize: Int = DEFAULT_PAGE_SIZE,
): Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>> {
return either {
repository
.getTxHistoryItems(network = network, pageSize = pageSize)
.getTxHistoryItems(currency = currency, pageSize = pageSize)
.catch { raise(TxHistoryListError.DataError(it)) }
}
}

View file

@ -6,16 +6,12 @@ import com.tangem.common.Provider
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistoryItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
import com.tangem.features.tokendetails.impl.R
import com.tangem.utils.converter.Converter
import com.tangem.utils.extensions.isToday
import com.tangem.utils.extensions.isYesterday
import com.tangem.utils.toBriefAddressFormat
import com.tangem.utils.toFormattedCurrencyString
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -25,7 +21,6 @@ import kotlinx.coroutines.flow.update
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormatterBuilder
import java.math.BigDecimal
import java.util.Locale
internal class TokenDetailsTxHistoryItemFlowConverter(
@ -35,6 +30,10 @@ internal class TokenDetailsTxHistoryItemFlowConverter(
private val clickIntents: TokenDetailsClickIntents,
) : Converter<Flow<PagingData<TxHistoryItem>>, TxHistoryState> {
private val txHistoryItemConverter by lazy {
TokenDetailsTxHistoryTransactionStateConverter(symbol = symbol, decimals = decimals)
}
/** Example, 2 Aug, 2023 */
private val dateFormatter by lazy {
DateTimeFormatterBuilder()
@ -84,62 +83,7 @@ internal class TokenDetailsTxHistoryItemFlowConverter(
}
private fun createTransactionState(item: TxHistoryItem): TransactionState {
return when (item.type) {
TxHistoryItem.TransactionType.Transfer -> {
when (val direction = item.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> {
createIncomingTransferTransaction(item, direction)
}
is TxHistoryItem.TransactionDirection.Outgoing -> {
createOutgoingTransferTransaction(item, direction)
}
}
}
}
}
private fun createIncomingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Incoming,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Receive(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
)
}
}
private fun createOutgoingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Outgoing,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Send(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
)
}
}
private fun BigDecimal.toCryptoCurrencyFormat(): String {
return toFormattedCurrencyString(currency = symbol, decimals = decimals)
return txHistoryItemConverter.convert(value = item)
}
private fun PagingData<TxHistoryItemState>.insertGroupTitle(): PagingData<TxHistoryItemState> {
@ -185,14 +129,6 @@ internal class TokenDetailsTxHistoryItemFlowConverter(
}
}
/**
* Get timestamp without formatting.
* It's life hack that help us to add transaction's group title to flow.
*
* @see [convert]
*/
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
private fun TxHistoryItemState?.getTimestamp(): Long? {
return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) {
val txContent = this.state as TransactionState.Content
@ -225,9 +161,4 @@ internal class TokenDetailsTxHistoryItemFlowConverter(
DateTime(this.toLong(), DateTimeZone.getDefault()),
)
}
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
}
}

View file

@ -29,60 +29,116 @@ internal class TokenDetailsTxHistoryToTransactionStateConverter(
}
override fun convert(value: TxHistoryItem): TransactionState {
return when (value.type) {
TxHistoryItem.TransactionType.Transfer -> {
when (val direction = value.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> {
createIncomingTransferTransaction(value, direction)
}
is TxHistoryItem.TransactionDirection.Outgoing -> {
createOutgoingTransferTransaction(value, direction)
}
}
}
}
return createTransactionStateItem(item = value)
}
private fun createIncomingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Incoming,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Receive(
// TODO: Finalize transaction types [REDACTED_JIRA]
private fun createTransactionStateItem(item: TxHistoryItem): TransactionState {
return when (val type = item.type) {
TxHistoryItem.TransactionType.Transfer -> mapTransfer(item)
TxHistoryItem.TransactionType.Approve -> mapApprove(item)
TxHistoryItem.TransactionType.Swap -> mapSwap(item)
TxHistoryItem.TransactionType.Deposit -> TransactionState.Custom(
txHash = item.txHash,
address = direction.extractAddress(),
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str("Deposit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
TxHistoryItem.TransactionType.Submit -> TransactionState.Custom(
txHash = item.txHash,
address = direction.extractAddress(),
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str("Submit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Supply -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str("Supply"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str("Unoswap"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str("Withdraw"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
title = TextReference.Str(type.id),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
}
}
private fun createOutgoingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Outgoing,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Send(
private fun mapTransfer(item: TxHistoryItem): TransactionState {
return when (item.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Receive(
txHash = item.txHash,
address = direction.extractAddress(),
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Send(
txHash = item.txHash,
address = direction.extractAddress(),
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
)
}
}
private fun mapApprove(item: TxHistoryItem): TransactionState {
return TransactionState.Approve(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
)
}
private fun mapSwap(item: TxHistoryItem): TransactionState {
return TransactionState.Swap(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
status = item.status.tiUiStatus(),
)
}
private fun BigDecimal.toCryptoCurrencyFormat(): String {
return toFormattedCurrencyString(currency = symbol, decimals = decimals)
}
@ -91,4 +147,10 @@ internal class TokenDetailsTxHistoryToTransactionStateConverter(
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
}
private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) {
TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed
TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed
TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed
}
}

View file

@ -0,0 +1,150 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.features.tokendetails.impl.R
import com.tangem.utils.converter.Converter
import com.tangem.utils.toBriefAddressFormat
import com.tangem.utils.toFormattedCurrencyString
import java.math.BigDecimal
internal class TokenDetailsTxHistoryTransactionStateConverter(
private val symbol: String,
private val decimals: Int,
) : Converter<TxHistoryItem, TransactionState> {
override fun convert(value: TxHistoryItem): TransactionState {
return createTransactionStateItem(item = value)
}
// TODO: Finalize transaction types [REDACTED_JIRA]
private fun createTransactionStateItem(item: TxHistoryItem): TransactionState {
return when (val type = item.type) {
TxHistoryItem.TransactionType.Transfer -> mapTransfer(item)
TxHistoryItem.TransactionType.Approve -> mapApprove(item)
TxHistoryItem.TransactionType.Swap -> mapSwap(item)
TxHistoryItem.TransactionType.Deposit -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Deposit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Submit -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Submit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Supply -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Supply"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Unoswap"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Withdraw"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str(type.id),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
}
}
private fun mapTransfer(item: TxHistoryItem): TransactionState {
return when (item.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Receive(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Send(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
}
private fun mapApprove(item: TxHistoryItem): TransactionState {
return TransactionState.Approve(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
private fun mapSwap(item: TxHistoryItem): TransactionState {
return TransactionState.Swap(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
/**
* Get timestamp without formatting.
* It's life hack that help us to add transaction's group title to flow.
*
* @see [convert]
*/
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
private fun BigDecimal.toCryptoCurrencyFormat(): String {
return toFormattedCurrencyString(currency = symbol, decimals = decimals)
}
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
}
private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) {
TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed
TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed
TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed
}
}

View file

@ -170,9 +170,7 @@ internal class TokenDetailsViewModel @Inject constructor(
txHistoryItemsCountEither.onRight {
uiState = stateFactory.getLoadedTxHistoryState(
txHistoryEither = txHistoryItemsUseCase(
network = cryptoCurrency.network,
).map {
txHistoryEither = txHistoryItemsUseCase(currency = cryptoCurrency).map {
it.cachedIn(viewModelScope)
},
)

View file

@ -418,20 +418,22 @@ internal object WalletPreviewData {
listOf(
TxHistoryState.TxHistoryItemState.GroupTitle("Today"),
TxHistoryState.TxHistoryItemState.Transaction(
TransactionState.Sending(
TransactionState.Send(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "-0.500913 BTC",
timestamp = "8:41",
status = TransactionState.Content.Status.Unconfirmed,
),
),
TxHistoryState.TxHistoryItemState.GroupTitle("Yesterday"),
TxHistoryState.TxHistoryItemState.Transaction(
TransactionState.Sending(
TransactionState.Send(
txHash = UUID.randomUUID().toString(),
address = TextReference.Str("33BddS...ga2B"),
amount = "-0.500913 BTC",
timestamp = "8:41",
status = TransactionState.Content.Status.Confirmed,
),
),
),

View file

@ -7,17 +7,13 @@ import com.tangem.common.Provider
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistoryItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
import com.tangem.utils.converter.Converter
import com.tangem.utils.extensions.isToday
import com.tangem.utils.extensions.isYesterday
import com.tangem.utils.toBriefAddressFormat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -27,7 +23,6 @@ import kotlinx.coroutines.flow.update
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormatterBuilder
import java.math.BigDecimal
import java.util.Locale
/**
@ -45,6 +40,10 @@ internal class WalletTxHistoryItemFlowConverter(
private val clickIntents: WalletClickIntents,
) : Converter<Flow<PagingData<TxHistoryItem>>, TxHistoryState?> {
private val txHistoryItemConverter by lazy {
WalletTxHistoryTransactionStateConverter(symbol = blockchain.currency, decimals = blockchain.decimals())
}
/** Example, 2 Aug, 2023 */
private val dateFormatter by lazy {
DateTimeFormatterBuilder()
@ -95,68 +94,7 @@ internal class WalletTxHistoryItemFlowConverter(
}
private fun createTransactionState(item: TxHistoryItem): TransactionState {
return when (item.type) {
TxHistoryItem.TransactionType.Transfer -> {
when (val direction = item.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> {
createIncomingTransferTransaction(item, direction, blockchain)
}
is TxHistoryItem.TransactionDirection.Outgoing -> {
createOutgoingTransferTransaction(item, direction, blockchain)
}
}
}
}
}
private fun createIncomingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Incoming,
blockchain: Blockchain,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Receive(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
timestamp = item.getRawTimestamp(),
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
timestamp = item.getRawTimestamp(),
)
}
}
private fun createOutgoingTransferTransaction(
item: TxHistoryItem,
direction: TxHistoryItem.TransactionDirection.Outgoing,
blockchain: Blockchain,
): TransactionState {
return when (item.status) {
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Send(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
timestamp = item.getRawTimestamp(),
)
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
txHash = item.txHash,
address = direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
timestamp = item.getRawTimestamp(),
)
}
}
private fun BigDecimal.toCryptoCurrencyFormat(blockchain: Blockchain): String {
return BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = this,
cryptoCurrency = blockchain.currency,
decimals = blockchain.decimals(),
)
return txHistoryItemConverter.convert(value = item)
}
private fun PagingData<TxHistoryItemState>.insertGroupTitle(): PagingData<TxHistoryItemState> {
@ -202,14 +140,6 @@ internal class WalletTxHistoryItemFlowConverter(
}
}
/**
* Get timestamp without formatting.
* It's life hack that help us to add transaction's group title to flow.
*
* @see [convert]
*/
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
private fun TxHistoryItemState?.getTimestamp(): Long? {
return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) {
val txContent = this.state as TransactionState.Content
@ -242,9 +172,4 @@ internal class WalletTxHistoryItemFlowConverter(
DateTime(this.toLong(), DateTimeZone.getDefault()),
)
}
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
}
}

View file

@ -0,0 +1,150 @@
package com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.feature.wallet.impl.R
import com.tangem.utils.converter.Converter
import com.tangem.utils.toBriefAddressFormat
import com.tangem.utils.toFormattedCurrencyString
import java.math.BigDecimal
class WalletTxHistoryTransactionStateConverter(
private val symbol: String,
private val decimals: Int,
) : Converter<TxHistoryItem, TransactionState> {
override fun convert(value: TxHistoryItem): TransactionState {
return createTransactionStateItem(item = value)
}
// TODO: Finalize transaction types [REDACTED_JIRA]
private fun createTransactionStateItem(item: TxHistoryItem): TransactionState {
return when (val type = item.type) {
TxHistoryItem.TransactionType.Transfer -> mapTransfer(item)
TxHistoryItem.TransactionType.Approve -> mapApprove(item)
TxHistoryItem.TransactionType.Swap -> mapSwap(item)
TxHistoryItem.TransactionType.Deposit -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Deposit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Submit -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Submit"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Supply -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Supply"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Unoswap"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str("Withdraw"),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
title = TextReference.Str(type.id),
subtitle = item.direction.extractAddress(),
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
)
}
}
private fun mapTransfer(item: TxHistoryItem): TransactionState {
return when (item.direction) {
is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Receive(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Send(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
}
private fun mapApprove(item: TxHistoryItem): TransactionState {
return TransactionState.Approve(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
private fun mapSwap(item: TxHistoryItem): TransactionState {
return TransactionState.Swap(
txHash = item.txHash,
address = item.direction.extractAddress(),
amount = item.amount.toCryptoCurrencyFormat(),
timestamp = item.getRawTimestamp(),
status = item.status.tiUiStatus(),
)
}
/**
* Get timestamp without formatting.
* It's life hack that help us to add transaction's group title to flow.
*
* @see [convert]
*/
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
private fun BigDecimal.toCryptoCurrencyFormat(): String {
return toFormattedCurrencyString(currency = symbol, decimals = decimals)
}
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
}
private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) {
TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed
TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed
TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed
}
}

View file

@ -38,7 +38,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkGroup
import com.tangem.domain.tokens.model.TokenList
import com.tangem.domain.tokens.models.CryptoCurrency
import com.tangem.domain.tokens.models.Network
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
import com.tangem.domain.userwallets.UserWalletBuilder
@ -757,9 +756,9 @@ internal class WalletViewModel @Inject constructor(
updateNotifications(index)
}
private fun updateTxHistory(network: Network) {
private fun updateTxHistory(currency: CryptoCurrency) {
viewModelScope.launch(dispatchers.io) {
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(network)
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(currency.network)
uiState = stateFactory.getLoadingTxHistoryState(
itemsCountEither = txHistoryItemsCountEither,
@ -767,9 +766,7 @@ internal class WalletViewModel @Inject constructor(
txHistoryItemsCountEither.onRight {
uiState = stateFactory.getLoadedTxHistoryState(
txHistoryEither = txHistoryItemsUseCase(
network,
).map {
txHistoryEither = txHistoryItemsUseCase(currency = currency).map {
it.cachedIn(viewModelScope)
},
)
@ -786,7 +783,7 @@ internal class WalletViewModel @Inject constructor(
maybeCryptoCurrencyStatus.onRight { status ->
singleWalletCryptoCurrencyStatus = status
updateButtons(userWalletId = userWalletId, currencyStatus = status)
updateTxHistory(status.currency.network)
updateTxHistory(status.currency)
}
}
.flowOn(dispatchers.io)

View file

@ -81,7 +81,7 @@ okHttp-prettyLogging = "3.1.0"
# endregion Other libraries
# region Tangem
tangemBlockchainSdk = "develop-350"
tangemBlockchainSdk = "develop-351"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-297"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds