Updated on 2026-08-14
This commit is contained in:
parent
164b6e3c71
commit
9cac096ce2
14 changed files with 239 additions and 113 deletions
|
|
@ -17,6 +17,7 @@ dependencies {
|
|||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Project - Data */
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package com.tangem.data.tokens.utils
|
|||
|
||||
import com.tangem.domain.tokens.model.NetworkAddress
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.PendingTransaction
|
||||
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.walletmanager.model.CryptoCurrencyAmount
|
||||
import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
|
|
@ -31,7 +31,6 @@ internal class NetworkStatusFactory {
|
|||
address = getNetworkAddress(result.defaultAddress, result.addresses),
|
||||
amounts = formatAmounts(result.currenciesAmounts, currencies),
|
||||
pendingTransactions = formatTransactions(
|
||||
networksAddresses = result.addresses,
|
||||
transactions = result.currentTransactions,
|
||||
currencies = currencies,
|
||||
),
|
||||
|
|
@ -67,10 +66,9 @@ internal class NetworkStatusFactory {
|
|||
}
|
||||
|
||||
private fun formatTransactions(
|
||||
networksAddresses: Set<String>,
|
||||
transactions: Set<CryptoCurrencyTransaction>,
|
||||
currencies: Set<CryptoCurrency>,
|
||||
): Map<CryptoCurrency.ID, Set<PendingTransaction>> {
|
||||
): Map<CryptoCurrency.ID, Set<TxHistoryItem>> {
|
||||
if (transactions.isEmpty()) return emptyMap()
|
||||
|
||||
return currencies
|
||||
|
|
@ -87,48 +85,13 @@ internal class NetworkStatusFactory {
|
|||
}
|
||||
}
|
||||
|
||||
currency.id to createCurrentTransactions(networksAddresses, currencyTransactions)
|
||||
currency.id to createCurrentTransactions(currencyTransactions)
|
||||
}
|
||||
.toMap()
|
||||
}
|
||||
|
||||
private fun createCurrentTransactions(
|
||||
networksAddresses: Set<String>,
|
||||
transactions: Set<CryptoCurrencyTransaction>,
|
||||
): Set<PendingTransaction> {
|
||||
return transactions.mapNotNullTo(hashSetOf()) { createCurrentTransaction(networksAddresses, it) }
|
||||
}
|
||||
|
||||
private fun createCurrentTransaction(
|
||||
networksAddresses: Set<String>,
|
||||
transaction: CryptoCurrencyTransaction,
|
||||
): PendingTransaction? {
|
||||
val direction = when {
|
||||
transaction.toAddress in networksAddresses -> PendingTransaction.Direction.Incoming(
|
||||
fromAddress = transaction.fromAddress,
|
||||
)
|
||||
transaction.fromAddress in networksAddresses -> PendingTransaction.Direction.Outgoing(
|
||||
toAddress = transaction.toAddress,
|
||||
)
|
||||
else -> {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to find transaction direction
|
||||
|- To address: ${transaction.toAddress}
|
||||
|- From address: ${transaction.fromAddress}
|
||||
|- Network addresses: $networksAddresses
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return PendingTransaction(
|
||||
amount = transaction.amount,
|
||||
direction = direction,
|
||||
sentAt = transaction.sentAt,
|
||||
)
|
||||
private fun createCurrentTransactions(transactions: Set<CryptoCurrencyTransaction>): Set<TxHistoryItem> {
|
||||
return transactions.mapTo(hashSetOf()) { it.txHistoryItem }
|
||||
}
|
||||
|
||||
private fun getNetworkAddress(defaultAddress: String, availableAddresses: Set<String>): NetworkAddress {
|
||||
|
|
|
|||
|
|
@ -1,28 +1,17 @@
|
|||
package com.tangem.domain.walletmanager.model
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import java.math.BigDecimal
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
|
||||
// TODO: [REDACTED_JIRA] move to txhistory module
|
||||
sealed class CryptoCurrencyTransaction {
|
||||
|
||||
abstract val amount: BigDecimal
|
||||
abstract val fromAddress: String?
|
||||
abstract val toAddress: String?
|
||||
abstract val sentAt: DateTime
|
||||
abstract val txHistoryItem: TxHistoryItem
|
||||
|
||||
data class Coin(
|
||||
override val amount: BigDecimal,
|
||||
override val fromAddress: String?,
|
||||
override val toAddress: String?,
|
||||
override val sentAt: DateTime,
|
||||
) : CryptoCurrencyTransaction()
|
||||
data class Coin(override val txHistoryItem: TxHistoryItem) : CryptoCurrencyTransaction()
|
||||
|
||||
data class Token(
|
||||
val tokenId: String?,
|
||||
val tokenContractAddress: String,
|
||||
override val amount: BigDecimal,
|
||||
override val fromAddress: String?,
|
||||
override val toAddress: String?,
|
||||
override val sentAt: DateTime,
|
||||
override val txHistoryItem: TxHistoryItem,
|
||||
) : CryptoCurrencyTransaction()
|
||||
}
|
||||
|
|
@ -3,37 +3,37 @@ package com.tangem.domain.walletmanager.utils
|
|||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.address.Address
|
||||
import com.tangem.domain.common.extensions.amountToCreateAccount
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount
|
||||
import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import org.joda.time.Instant
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import java.util.Calendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
internal class UpdateWalletManagerResultFactory {
|
||||
|
||||
fun getResult(walletManager: WalletManager): UpdateWalletManagerResult.Verified {
|
||||
val wallet = walletManager.wallet
|
||||
val addresses = getAvailableAddresses(wallet.addresses)
|
||||
|
||||
return UpdateWalletManagerResult.Verified(
|
||||
defaultAddress = wallet.address,
|
||||
addresses = getAvailableAddresses(wallet.addresses),
|
||||
addresses = addresses,
|
||||
currenciesAmounts = getTokensAmounts(wallet.amounts.values.toSet()),
|
||||
currentTransactions = getCurrentTransactions(wallet.recentTransactions.toSet()),
|
||||
currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()),
|
||||
)
|
||||
}
|
||||
|
||||
fun getDemoResult(walletManager: WalletManager, demoAmount: Amount): UpdateWalletManagerResult.Verified {
|
||||
val wallet = walletManager.wallet
|
||||
val addresses = getAvailableAddresses(wallet.addresses)
|
||||
|
||||
return UpdateWalletManagerResult.Verified(
|
||||
defaultAddress = wallet.address,
|
||||
addresses = getAvailableAddresses(wallet.addresses),
|
||||
addresses = addresses,
|
||||
currenciesAmounts = getDemoTokensAmounts(demoAmount, walletManager.cardTokens),
|
||||
currentTransactions = getCurrentTransactions(wallet.recentTransactions.toSet()),
|
||||
currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -70,12 +70,15 @@ internal class UpdateWalletManagerResultFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getCurrentTransactions(recentTransactions: Set<TransactionData>): Set<CryptoCurrencyTransaction> {
|
||||
private fun getCurrentTransactions(
|
||||
walletAddresses: Set<String>,
|
||||
recentTransactions: Set<TransactionData>,
|
||||
): Set<CryptoCurrencyTransaction> {
|
||||
val unconfirmedTransactions = recentTransactions.filter {
|
||||
it.status == TransactionStatus.Unconfirmed
|
||||
}
|
||||
|
||||
return unconfirmedTransactions.mapNotNullTo(hashSetOf(), ::createCurrencyTransaction)
|
||||
return unconfirmedTransactions.mapNotNullTo(hashSetOf()) { createCurrencyTransaction(walletAddresses, it) }
|
||||
}
|
||||
|
||||
private fun createCurrencyAmount(amount: Amount): CryptoCurrencyAmount? {
|
||||
|
|
@ -92,31 +95,78 @@ internal class UpdateWalletManagerResultFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createCurrencyTransaction(data: TransactionData): CryptoCurrencyTransaction? {
|
||||
val fromAddress = takeAddressIfNotUnknown(data.sourceAddress)
|
||||
val toAddress = takeAddressIfNotUnknown(data.destinationAddress)
|
||||
val amount = getTransactionAmountValue(data.amount) ?: return null
|
||||
val sentAt = getTransactionSentTime(data.date) ?: return null
|
||||
|
||||
private fun createCurrencyTransaction(
|
||||
walletAddresses: Set<String>,
|
||||
data: TransactionData,
|
||||
): CryptoCurrencyTransaction? {
|
||||
return when (val type = data.amount.type) {
|
||||
is AmountType.Coin -> CryptoCurrencyTransaction.Coin(
|
||||
amount = amount,
|
||||
fromAddress = fromAddress,
|
||||
toAddress = toAddress,
|
||||
sentAt = sentAt,
|
||||
)
|
||||
is AmountType.Token -> CryptoCurrencyTransaction.Token(
|
||||
tokenId = type.token.id,
|
||||
tokenContractAddress = type.token.contractAddress,
|
||||
amount = amount,
|
||||
fromAddress = fromAddress,
|
||||
toAddress = toAddress,
|
||||
sentAt = sentAt,
|
||||
)
|
||||
is AmountType.Coin -> {
|
||||
val txHistoryItem = createTxHistoryItem(walletAddresses, data) ?: return null
|
||||
CryptoCurrencyTransaction.Coin(txHistoryItem)
|
||||
}
|
||||
is AmountType.Token -> {
|
||||
val txHistoryItem = createTxHistoryItem(walletAddresses, data) ?: return null
|
||||
CryptoCurrencyTransaction.Token(
|
||||
tokenId = type.token.id,
|
||||
tokenContractAddress = type.token.contractAddress,
|
||||
txHistoryItem = txHistoryItem,
|
||||
)
|
||||
}
|
||||
is AmountType.Reserve -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTxHistoryItem(walletAddresses: Set<String>, data: TransactionData): TxHistoryItem? {
|
||||
val direction = extractDirection(walletAddresses, data) ?: run {
|
||||
Timber.w("Can not determine address for $data")
|
||||
return null
|
||||
}
|
||||
val hash = data.hash ?: return null
|
||||
val millis = data.date?.timeInMillis ?: return null
|
||||
val amount = getTransactionAmountValue(data.amount) ?: return null
|
||||
|
||||
return TxHistoryItem(
|
||||
txHash = hash,
|
||||
timestampInMillis = TimeUnit.SECONDS.toMillis(millis),
|
||||
direction = direction,
|
||||
status = when (data.status) {
|
||||
TransactionStatus.Confirmed -> TxHistoryItem.TxStatus.Confirmed
|
||||
TransactionStatus.Unconfirmed -> TxHistoryItem.TxStatus.Unconfirmed
|
||||
},
|
||||
type = TxHistoryItem.TransactionType.Transfer,
|
||||
amount = amount,
|
||||
)
|
||||
}
|
||||
|
||||
private fun extractDirection(
|
||||
walletAddresses: Set<String>,
|
||||
data: TransactionData,
|
||||
): TxHistoryItem.TransactionDirection? {
|
||||
val fromAddress = data.sourceAddress
|
||||
val toAddress = data.destinationAddress
|
||||
|
||||
return when {
|
||||
toAddress in walletAddresses -> {
|
||||
TxHistoryItem.TransactionDirection.Incoming(TxHistoryItem.Address.Single(fromAddress))
|
||||
}
|
||||
fromAddress in walletAddresses -> {
|
||||
TxHistoryItem.TransactionDirection.Outgoing(TxHistoryItem.Address.Single(toAddress))
|
||||
}
|
||||
else -> {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to find transaction direction
|
||||
|- To address: ${data.destinationAddress}
|
||||
|- From address: ${data.sourceAddress}
|
||||
|- Network addresses: $walletAddresses
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAvailableAddresses(addresses: Set<Address>): Set<String> {
|
||||
return addresses.mapTo(hashSetOf()) { it.value }
|
||||
}
|
||||
|
|
@ -140,24 +190,4 @@ internal class UpdateWalletManagerResultFactory {
|
|||
|
||||
return value
|
||||
}
|
||||
|
||||
private fun getTransactionSentTime(date: Calendar?): DateTime? {
|
||||
if (date == null) {
|
||||
Timber.e("Transaction date must not be null")
|
||||
return null
|
||||
}
|
||||
|
||||
val instant = Instant.ofEpochMilli(date.timeInMillis)
|
||||
val timeZone = DateTimeZone.forTimeZone(date.timeZone)
|
||||
|
||||
return instant.toDateTime(timeZone)
|
||||
}
|
||||
|
||||
private fun takeAddressIfNotUnknown(address: String): String? {
|
||||
return address.takeIf { it.isNotBlank() && it != UNKNOWN_TRANSACTION_ADDRESS }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val UNKNOWN_TRANSACTION_ADDRESS = "unknown"
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ dependencies {
|
|||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.tokens.model
|
||||
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +40,7 @@ data class CryptoCurrencyStatus(
|
|||
open val hasCurrentNetworkTransactions: Boolean = false
|
||||
|
||||
/** The pending cryptocurrency transactions. */
|
||||
open val pendingTransactions: Set<PendingTransaction> = emptySet()
|
||||
open val pendingTransactions: Set<TxHistoryItem> = emptySet()
|
||||
|
||||
/** The network address */
|
||||
open val networkAddress: NetworkAddress? = null
|
||||
|
|
@ -74,7 +75,7 @@ data class CryptoCurrencyStatus(
|
|||
override val fiatRate: BigDecimal,
|
||||
override val priceChange: BigDecimal,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<PendingTransaction>,
|
||||
override val pendingTransactions: Set<TxHistoryItem>,
|
||||
override val networkAddress: NetworkAddress?,
|
||||
) : Status()
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ data class CryptoCurrencyStatus(
|
|||
override val fiatRate: BigDecimal?,
|
||||
override val priceChange: BigDecimal?,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<PendingTransaction>,
|
||||
override val pendingTransactions: Set<TxHistoryItem>,
|
||||
override val networkAddress: NetworkAddress?,
|
||||
) : Status()
|
||||
|
||||
|
|
@ -110,7 +111,7 @@ data class CryptoCurrencyStatus(
|
|||
data class NoQuote(
|
||||
override val amount: BigDecimal,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<PendingTransaction>,
|
||||
override val pendingTransactions: Set<TxHistoryItem>,
|
||||
override val networkAddress: NetworkAddress?,
|
||||
) : Status()
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.tokens.model
|
|||
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -44,7 +45,7 @@ data class NetworkStatus(
|
|||
data class Verified(
|
||||
val address: NetworkAddress,
|
||||
val amounts: Map<CryptoCurrency.ID, BigDecimal>,
|
||||
val pendingTransactions: Map<CryptoCurrency.ID, Set<PendingTransaction>>,
|
||||
val pendingTransactions: Map<CryptoCurrency.ID, Set<TxHistoryItem>>,
|
||||
) : Status()
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -82,5 +82,6 @@ internal object TokenDetailsPreviewData {
|
|||
),
|
||||
),
|
||||
dialogConfig = null,
|
||||
pendingTxs = persistentListOf(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.state
|
||||
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsDialogConfig
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
||||
internal data class TokenDetailsState(
|
||||
val topAppBarConfig: TokenDetailsTopAppBarConfig,
|
||||
val tokenInfoBlockState: TokenInfoBlockState,
|
||||
val tokenBalanceBlockState: TokenDetailsBalanceBlockState,
|
||||
val marketPriceBlockState: MarketPriceBlockState,
|
||||
val pendingTxs: PersistentList<TransactionState>,
|
||||
val txHistoryState: TxHistoryState,
|
||||
val dialogConfig: TokenDetailsDialogConfig?,
|
||||
)
|
||||
|
|
@ -10,14 +10,22 @@ import com.tangem.domain.tokens.error.CurrencyStatusError
|
|||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryToTransactionStateConverter
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class TokenDetailsLoadedBalanceConverter(
|
||||
private val currentStateProvider: Provider<TokenDetailsState>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val symbol: String,
|
||||
private val decimals: Int,
|
||||
) : Converter<Either<CurrencyStatusError, CryptoCurrencyStatus>, TokenDetailsState> {
|
||||
|
||||
private val txHistoryItemConverter by lazy {
|
||||
TokenDetailsTxHistoryToTransactionStateConverter(symbol, decimals)
|
||||
}
|
||||
|
||||
override fun convert(value: Either<CurrencyStatusError, CryptoCurrencyStatus>): TokenDetailsState {
|
||||
return value.fold(ifLeft = { convertError() }, ifRight = ::convert)
|
||||
}
|
||||
|
|
@ -33,6 +41,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
return state.copy(
|
||||
tokenBalanceBlockState = getBalanceState(state.tokenBalanceBlockState, status),
|
||||
marketPriceBlockState = getMarketPriceState(status = status.value, currencyName = currencyName),
|
||||
pendingTxs = status.value.pendingTransactions.map(txHistoryItemConverter::convert).toPersistentList(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
actionButtons = createButtons(),
|
||||
),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(value.cryptoCurrency.name),
|
||||
pendingTxs = persistentListOf(),
|
||||
txHistoryState = TxHistoryState.Content(
|
||||
contentItems = MutableStateFlow(
|
||||
value = TxHistoryState.getDefaultLoadingTransactions(clickIntents::onExploreClick),
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ internal class TokenDetailsStateFactory(
|
|||
TokenDetailsLoadedBalanceConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
symbol = symbol,
|
||||
decimals = decimals,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
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 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 TokenDetailsTxHistoryToTransactionStateConverter(
|
||||
private val symbol: String,
|
||||
private val decimals: Int,
|
||||
) : Converter<TxHistoryItem, TransactionState> {
|
||||
|
||||
/** Example, 13:35 */
|
||||
private val timeFormatter by lazy {
|
||||
DateTimeFormatterBuilder()
|
||||
.appendHourOfDay(1)
|
||||
.appendLiteral(':')
|
||||
.appendMinuteOfHour(2)
|
||||
.toFormatter()
|
||||
.withLocale(Locale.getDefault())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = timeFormatter.print(DateTime(item.timestampInMillis, DateTimeZone.getDefault())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,23 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.Transaction
|
||||
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.txHistoryItems
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -19,6 +27,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.T
|
|||
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenDetailsDialogs
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenDetailsTopAppBar
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenInfoBlock
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
||||
@Composable
|
||||
internal fun TokenDetailsScreen(state: TokenDetailsState) {
|
||||
|
|
@ -55,6 +64,14 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) {
|
|||
contentType = MarketPriceBlockState::class.java,
|
||||
content = { MarketPriceBlock(modifier = itemModifier, state = state.marketPriceBlockState) },
|
||||
)
|
||||
if (state.txHistoryState is TxHistoryState.NotSupported && state.pendingTxs.isNotEmpty()) {
|
||||
item {
|
||||
PendingTxsBlock(
|
||||
pendingTxs = state.pendingTxs,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
txHistoryItems(state = state.txHistoryState, txHistoryItems = txHistoryItems)
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +79,19 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PendingTxsBlock(pendingTxs: PersistentList<TransactionState>, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.clip(shape = TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(color = TangemTheme.colors.background.primary),
|
||||
verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing8),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
) {
|
||||
pendingTxs.fastForEach { Transaction(state = it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_TokenDetailsScreen_LightTheme() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue