diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt index 1c4bc06044..0de90f000b 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt @@ -1,6 +1,9 @@ package com.tangem.tap.di.domain +import android.content.Context +import com.squareup.moshi.Moshi import com.tangem.datasource.config.ConfigManager +import com.tangem.datasource.di.SdkMoshi import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.domain.walletmanager.DefaultWalletManagersFacade @@ -8,6 +11,7 @@ import com.tangem.domain.walletmanager.WalletManagersFacade import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @@ -21,7 +25,15 @@ internal object WalletManagersFacadeModule { walletManagersStore: WalletManagersStore, userWalletsStore: UserWalletsStore, configManager: ConfigManager, + @ApplicationContext appContext: Context, + @SdkMoshi moshi: Moshi, ): WalletManagersFacade { - return DefaultWalletManagersFacade(walletManagersStore, userWalletsStore, configManager) + return DefaultWalletManagersFacade( + walletManagersStore = walletManagersStore, + userWalletsStore = userWalletsStore, + configManager = configManager, + assetManager = appContext.assets, + moshi = moshi, + ) } } \ No newline at end of file diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index d970534eb9..44bf68de60 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -453,6 +453,7 @@ Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию. Несколько адресов История транзакций в настоящее время не поддерживается для этого блокчейна. Но не волнуйтесь, мы работаем над этим! А пока вы можете проверить ее в обозревателе. + Операция от: %s на: %s В процессе… diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index d677e0eb3c..7282434764 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -469,6 +469,7 @@ Failed to load transaction history.\nClick on reload button to update the information. Multiple addresses Transaction history is currently not supported for this blockchain. But don\'t worry, we\'re working on it! In the meantime you can check it in the explorer. + Operation from: %s to: %s In progress… diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt index e1947a8843..0abe2332ca 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt @@ -29,6 +29,7 @@ import com.tangem.core.ui.components.transactions.state.TransactionState.Content import com.tangem.core.ui.components.transactions.state.TransactionState.Content.Status import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import java.util.UUID @@ -137,22 +138,7 @@ private fun Icon(state: TransactionState, modifier: Modifier = Modifier) { ), ) { Icon( - painter = painterResource( - id = when (state.status) { - is Status.Failed -> R.drawable.ic_close_24 - else -> when (state) { - is TransactionState.Transfer -> { - when (state.direction) { - Direction.OUTGOING -> R.drawable.ic_arrow_up_24 - Direction.INCOMING -> 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 - } - }, - ), + painter = painterResource(id = state.iconRes), contentDescription = null, modifier = Modifier .size(TangemTheme.dimens.size20) @@ -189,12 +175,7 @@ private fun Title(state: TransactionState, modifier: Modifier = Modifier) { is TransactionState.Content -> { Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6)) { Text( - text = when (state) { - is TransactionState.Approve -> stringResource(R.string.common_approval) - is TransactionState.Transfer -> stringResource(R.string.common_transfer) - is TransactionState.Swap -> stringResource(R.string.common_swap) - is TransactionState.Custom -> state.title.resolveReference() - }, + text = state.title.resolveReference(), color = TangemTheme.colors.text.primary1, style = TangemTheme.typography.subtitle2, ) @@ -228,35 +209,7 @@ private fun Subtitle(state: TransactionState, modifier: Modifier = Modifier) { Text( text = when (state.status) { is Status.Failed -> stringResource(id = R.string.common_transaction_failed) - else -> when (state) { - is TransactionState.Transfer -> { - when (state.direction) { - Direction.OUTGOING -> stringResource( - id = R.string.transaction_history_transaction_to_address, - state.address.resolveReference(), - ) - Direction.INCOMING -> stringResource( - id = R.string.transaction_history_transaction_from_address, - state.address.resolveReference(), - ) - } - } - is TransactionState.Approve -> stringResource( - id = R.string.transaction_history_transaction_from_address, - state.address.resolveReference(), - ) - is TransactionState.Swap -> stringResource( - id = R.string.transaction_history_contract_address, - state.address.resolveReference(), - ) - is TransactionState.Custom -> stringResource( - id = when (state.direction) { - Direction.OUTGOING -> R.string.transaction_history_transaction_to_address - Direction.INCOMING -> R.string.transaction_history_transaction_from_address - }, - state.subtitle.resolveReference(), - ) - } + else -> state.subtitle.resolveReference() }, modifier = modifier, textAlign = TextAlign.Start, @@ -362,78 +315,98 @@ private fun Preview_TransactionItem_DarkTheme( private class TransactionItemStateProvider : CollectionPreviewParameterProvider( collection = listOf( - TransactionState.Transfer( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "-0.500913 BTC", timestamp = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, + iconRes = R.drawable.ic_arrow_up_24, + title = resourceReference(R.string.common_transfer), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Transfer( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Unconfirmed, direction = Direction.INCOMING, + iconRes = R.drawable.ic_arrow_down_24, + title = resourceReference(R.string.common_transfer), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Approve( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Unconfirmed, direction = Direction.OUTGOING, + iconRes = R.drawable.ic_doc_24, + title = resourceReference(R.string.common_approval), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Approve( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Failed, direction = Direction.OUTGOING, + iconRes = R.drawable.ic_doc_24, + title = resourceReference(R.string.common_approval), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Approve( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, + iconRes = R.drawable.ic_doc_24, + title = resourceReference(R.string.common_approval), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Swap( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Unconfirmed, direction = Direction.INCOMING, + iconRes = R.drawable.ic_arrow_down_24, + title = resourceReference(R.string.common_swap), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Custom( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Confirmed, direction = Direction.INCOMING, + iconRes = R.drawable.ic_doc_24, title = TextReference.Str("Submit"), subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), - TransactionState.Custom( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "+0.500913 BTC", timestamp = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, + iconRes = R.drawable.ic_arrow_up_24, title = TextReference.Str("Submit"), subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt index c513c83fba..2f7a5c22b9 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt @@ -1,5 +1,6 @@ package com.tangem.core.ui.components.transactions.state +import androidx.annotation.DrawableRes import com.tangem.core.ui.extensions.TextReference /** @@ -22,30 +23,18 @@ sealed interface TransactionState { * @property direction transaction direction * @property onClick Lambda be invoked when manage button is clicked */ - sealed class Content : TransactionState { - - abstract val address: TextReference - abstract val amount: String - abstract val timestamp: String - abstract val status: Status - abstract val direction: Direction - abstract val onClick: () -> Unit - - fun copySealed( - txHash: String = this.txHash, - address: TextReference = this.address, - amount: String = this.amount, - timestamp: String = this.timestamp, - status: Status = this.status, - direction: Direction = this.direction, - ): Content { - return when (this) { - is Approve -> copy(txHash, address, amount, timestamp, status, direction) - is Transfer -> copy(txHash, address, amount, timestamp, status, direction) - is Swap -> copy(txHash, address, amount, timestamp, status, direction) - is Custom -> copy(txHash, address, amount, timestamp, status, direction) - } - } + data class Content( + override val txHash: String, + val address: TextReference, + val amount: String, + val timestamp: String, + val status: Status, + val direction: Direction, + val onClick: () -> Unit, + @DrawableRes val iconRes: Int, + val title: TextReference, + val subtitle: TextReference, + ) : TransactionState { sealed class Status { object Failed : Status() @@ -59,75 +48,6 @@ sealed interface TransactionState { } } - /** - * Completed sending transaction state - * - * @property txHash transaction hash - * @property address address - * @property amount amount - * @property timestamp timestamp - * @property direction transaction direction - */ - data class Transfer( - override val txHash: String, - override val address: TextReference, - override val amount: String, - override val timestamp: String, - override val status: Status, - override val direction: Direction, - override val onClick: () -> Unit, - ) : Content() - - /** - * Completed approving transaction state - * - * @property txHash transaction hash - * @property address address - * @property amount amount - * @property timestamp timestamp - * @property direction transaction direction - */ - data class Approve( - override val txHash: String, - override val address: TextReference, - override val amount: String, - override val timestamp: String, - override val status: Status, - override val direction: Direction, - override val onClick: () -> Unit, - ) : Content() - - /** - * Completed swapping transaction state - * - * @property txHash transaction hash - * @property address address - * @property amount amount - * @property timestamp timestamp - * @property direction transaction direction - */ - data class Swap( - override val txHash: String, - override val address: TextReference, - override val amount: String, - override val timestamp: String, - override val status: Status, - override val direction: Direction, - override val onClick: () -> Unit, - ) : Content() - - data class Custom( - override val txHash: String, - override val address: TextReference, - override val amount: String, - override val timestamp: String, - override val status: Status, - override val direction: Direction, - override val onClick: () -> Unit, - val title: TextReference, - val subtitle: TextReference, - ) : Content() - /** * Loading state * diff --git a/domain/legacy/src/main/assets/contract_methods.json b/domain/legacy/src/main/assets/contract_methods.json new file mode 100644 index 0000000000..e07b98657c --- /dev/null +++ b/domain/legacy/src/main/assets/contract_methods.json @@ -0,0 +1,125 @@ +{ + "0xa9059cbb":{ + "info":"ERC20", + "source":"https://eips.ethereum.org/EIPS/eip-20", + "name":"transfer" + }, + "0x095ea7b3":{ + "info":"ERC20", + "source":"https://eips.ethereum.org/EIPS/eip-20", + "name":"approve" + }, + "0x357a150b":{ + "info":"ERC721", + "source":"https://eips.ethereum.org/EIPS/eip-721", + "name":"run" + }, + "0x23b872dd":{ + "info":"ERC721", + "source":"https://eips.ethereum.org/EIPS/eip-721", + "name":"transferFrom" + }, + "0x87201b41":{ + "info":"ERC721", + "source":"https://eips.ethereum.org/EIPS/eip-721", + "name":"fulfillAvailableAdvancedOrders" + }, + "0xe449f341":{ + "info":"ERC721", + "source":"https://eips.ethereum.org/EIPS/eip-721", + "name":"unstake" + }, + "0x84bb1e42":{ + "info":"ERC721", + "source":"https://eips.ethereum.org/EIPS/eip-721", + "name":"claim" + }, + "0xd48c03e5":{ + "info":"ERC1155", + "source":"https://eips.ethereum.org/EIPS/eip-1155", + "name":"mint" + }, + "0xe3afe0a3":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"withdrawal" + }, + "0xd6681042":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"withdrawal" + }, + "0x19aa6257":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"withdrawal" + }, + "0xacf41e4d":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"withdrawal" + }, + "0x7951b76f":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"withdrawal" + }, + "0xa1903eab":{ + "info":"Lido", + "source":"https://github.com/LedgerHQ/app-plugin-lido#smart-contracts", + "name":"submit" + }, + "0x617ba037":{ + "info":"AAVE", + "source":"https://etherscan.io/address/0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2", + "name":"supply" + }, + "0x69328dec":{ + "info":"AAVE", + "source":"https://etherscan.io/address/0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2", + "name":"withdraw" + }, + "0x3ccfd60b":{ + "info":"AAVE", + "source":"https://etherscan.io/address/0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2", + "name":"withdraw" + }, + "0x573ade81":{ + "info":"AAVE", + "source":"https://etherscan.io/address/0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2", + "name":"repay" + }, + "0xa415bcad":{ + "info":"AAVE", + "source":"https://etherscan.io/address/0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2", + "name":"borrow" + }, + "0x12aa3caf":{ + "info":"1inch v5", + "source":"https://github.com/LedgerHQ/app-plugin-1inch#functions-implemented", + "name":"swap" + }, + "0x7c025200":{ + "info":"1inch", + "source":"https://github.com/LedgerHQ/app-plugin-1inch#functions-implemented", + "name":"swap" + }, + "0x2e95b6c8":{ + "info":"1inch", + "source":"https://github.com/LedgerHQ/app-plugin-1inch#functions-implemented", + "name":"unoswap" + }, + "0x0502b1c5":{ + "info":"1inch", + "source":"https://github.com/LedgerHQ/app-plugin-1inch#functions-implemented", + "name":"unoswap" + }, + "0x3593564c": { + "info":"unoswap", + "source":"https://etherscan.io/address/0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "name":"execute" + }, + "0xd0e30db0": { + "name":"deposit" + } +} diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt index c1fbac9b0a..d74b6a9d58 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt @@ -4,6 +4,8 @@ import arrow.core.Either import arrow.core.raise.either import arrow.core.raise.ensureNotNull import arrow.core.right +import android.content.res.AssetManager +import com.squareup.moshi.Moshi import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider import com.tangem.blockchain.blockchains.solana.RentProvider import com.tangem.blockchain.common.* @@ -41,6 +43,8 @@ class DefaultWalletManagersFacade( private val walletManagersStore: WalletManagersStore, private val userWalletsStore: UserWalletsStore, configManager: ConfigManager, + assetManager: AssetManager, + moshi: Moshi, ) : WalletManagersFacade { private val demoConfig by lazy { DemoConfig() } @@ -48,7 +52,7 @@ class DefaultWalletManagersFacade( private val walletManagerFactory by lazy { WalletManagerFactory(configManager) } private val sdkTokenConverter by lazy { SdkTokenConverter() } private val txHistoryStateConverter by lazy { SdkTransactionHistoryStateConverter() } - private val txHistoryItemConverter by lazy { SdkTransactionHistoryItemConverter() } + private val txHistoryItemConverter by lazy { SdkTransactionHistoryItemConverter(assetManager, moshi) } override suspend fun update( userWalletId: UserWalletId, diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/SmartContractMethod.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/SmartContractMethod.kt new file mode 100644 index 0000000000..58996b7fd3 --- /dev/null +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/SmartContractMethod.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.walletmanager.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class SmartContractMethod( + @Json(name = "info") val info: String?, + @Json(name = "source") val source: String?, + @Json(name = "name") val name: String, +) \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionHistoryItemConverter.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionHistoryItemConverter.kt index d0f0ef7d65..8a25f01e31 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionHistoryItemConverter.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionHistoryItemConverter.kt @@ -1,44 +1,93 @@ package com.tangem.domain.walletmanager.utils +import android.content.res.AssetManager +import com.squareup.moshi.Moshi import com.tangem.blockchain.common.txhistory.TransactionHistoryItem import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.utils.converter.Converter import com.tangem.blockchain.common.txhistory.TransactionHistoryItem as SdkTransactionHistoryItem -internal class SdkTransactionHistoryItemConverter : Converter { +internal class SdkTransactionHistoryItemConverter( + assetManager: AssetManager, + moshi: Moshi, +) : Converter { + + private val typeConverter by lazy { + SdkTransactionTypeConverter(assetManager, moshi) + } override fun convert(value: SdkTransactionHistoryItem): TxHistoryItem = TxHistoryItem( txHash = value.txHash, timestampInMillis = value.timestamp, - direction = value.direction.toDomain(), + isOutgoing = value.isOutgoing, + destinationType = value.destinationType.toDomain(), + sourceType = value.sourceType.toDomain(), + interactionAddressType = value.extractInteractionAddressType(), status = when (value.status) { - TransactionHistoryItem.TransactionStatus.Confirmed -> TxHistoryItem.TransactionStatus.Confirmed - TransactionHistoryItem.TransactionStatus.Failed -> TxHistoryItem.TransactionStatus.Failed - TransactionHistoryItem.TransactionStatus.Unconfirmed -> TxHistoryItem.TransactionStatus.Unconfirmed - }, - 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 + SdkTransactionHistoryItem.TransactionStatus.Confirmed -> TxHistoryItem.TransactionStatus.Confirmed + SdkTransactionHistoryItem.TransactionStatus.Failed -> TxHistoryItem.TransactionStatus.Failed + SdkTransactionHistoryItem.TransactionStatus.Unconfirmed -> TxHistoryItem.TransactionStatus.Unconfirmed }, + type = typeConverter.convert(value.type), amount = requireNotNull(value.amount.value) { "Transaction amount value must not be null" }, ) - private fun TransactionHistoryItem.TransactionDirection.toDomain() = when (this) { - is TransactionHistoryItem.TransactionDirection.Incoming -> - TxHistoryItem.TransactionDirection.Incoming(address.toDomain()) - is TransactionHistoryItem.TransactionDirection.Outgoing -> - TxHistoryItem.TransactionDirection.Outgoing(address.toDomain()) + private fun SdkTransactionHistoryItem.SourceType.toDomain(): TxHistoryItem.SourceType = when (this) { + is TransactionHistoryItem.SourceType.Single -> TxHistoryItem.SourceType.Single(address) + is TransactionHistoryItem.SourceType.Multiple -> TxHistoryItem.SourceType.Multiple(addresses) } - private fun TransactionHistoryItem.Address.toDomain(): TxHistoryItem.Address = when (this) { - TransactionHistoryItem.Address.Multiple -> TxHistoryItem.Address.Multiple - is TransactionHistoryItem.Address.Single -> TxHistoryItem.Address.Single(rawAddress = rawAddress) + private fun SdkTransactionHistoryItem.DestinationType.toDomain(): TxHistoryItem.DestinationType = when (this) { + is SdkTransactionHistoryItem.DestinationType.Single -> TxHistoryItem.DestinationType.Single( + addressType.toDomain(), + ) + is SdkTransactionHistoryItem.DestinationType.Multiple -> TxHistoryItem.DestinationType.Multiple( + addressTypes.map { it.toDomain() }, + ) + } + + private fun SdkTransactionHistoryItem.AddressType.toDomain(): TxHistoryItem.AddressType = when (this) { + is SdkTransactionHistoryItem.AddressType.Contract -> TxHistoryItem.AddressType.Contract(address) + is SdkTransactionHistoryItem.AddressType.User -> TxHistoryItem.AddressType.User(address) + } + + private fun SdkTransactionHistoryItem.extractInteractionAddressType(): TxHistoryItem.InteractionAddressType { + return when (type) { + SdkTransactionHistoryItem.TransactionType.Transfer -> if (isOutgoing) { + mapToInteractionAddressType(destinationType = destinationType) + } else { + mapToInteractionAddressType(sourceType = sourceType) + } + is SdkTransactionHistoryItem.TransactionType.ContractMethod -> mapToInteractionAddressType(destinationType) + } + } + + private fun mapToInteractionAddressType( + destinationType: SdkTransactionHistoryItem.DestinationType, + ): TxHistoryItem.InteractionAddressType { + return when (destinationType) { + is TransactionHistoryItem.DestinationType.Multiple -> TxHistoryItem.InteractionAddressType.Multiple( + destinationType.addressTypes.map { it.address }, + ) + is TransactionHistoryItem.DestinationType.Single -> when (destinationType.addressType) { + is TransactionHistoryItem.AddressType.Contract -> TxHistoryItem.InteractionAddressType.Contract( + destinationType.addressType.address, + ) + is TransactionHistoryItem.AddressType.User -> TxHistoryItem.InteractionAddressType.User( + destinationType.addressType.address, + ) + } + } + } + + private fun mapToInteractionAddressType( + sourceType: SdkTransactionHistoryItem.SourceType, + ): TxHistoryItem.InteractionAddressType { + return when (sourceType) { + is TransactionHistoryItem.SourceType.Multiple -> TxHistoryItem.InteractionAddressType.Multiple( + sourceType.addresses, + ) + is TransactionHistoryItem.SourceType.Single -> TxHistoryItem.InteractionAddressType.User(sourceType.address) + } } } \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionTypeConverter.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionTypeConverter.kt new file mode 100644 index 0000000000..271e9d3209 --- /dev/null +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/SdkTransactionTypeConverter.kt @@ -0,0 +1,50 @@ +package com.tangem.domain.walletmanager.utils + +import android.content.res.AssetManager +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import com.tangem.blockchain.common.txhistory.TransactionHistoryItem +import com.tangem.domain.txhistory.models.TxHistoryItem +import com.tangem.domain.walletmanager.model.SmartContractMethod +import com.tangem.utils.converter.Converter +import okio.buffer +import okio.source + +class SdkTransactionTypeConverter( + private val assetManager: AssetManager, + private val moshi: Moshi, +) : Converter { + + private val adapter: JsonAdapter> by lazy { + moshi.adapter( + Types.newParameterizedType( + Map::class.java, + String::class.java, + SmartContractMethod::class.java, + ), + ) + } + private val smartContractMethods by lazy { readSmartContractMethods() } + + override fun convert(value: TransactionHistoryItem.TransactionType): TxHistoryItem.TransactionType { + return when (value) { + TransactionHistoryItem.TransactionType.Transfer -> TxHistoryItem.TransactionType.Transfer + is TransactionHistoryItem.TransactionType.ContractMethod -> { + return when (val name = smartContractMethods[value.id]?.name) { + "transfer" -> TxHistoryItem.TransactionType.Transfer + "approve" -> TxHistoryItem.TransactionType.Approve + "swap" -> TxHistoryItem.TransactionType.Swap + null -> TxHistoryItem.TransactionType.UnknownOperation + else -> TxHistoryItem.TransactionType.Operation(name = name.replaceFirstChar { it.titlecase() }) + } + } + } + } + + private fun readSmartContractMethods(): Map { + return assetManager.open("contract_methods.json").use { stream -> + adapter.fromJson(stream.source().buffer()) + } ?: emptyMap() + } +} \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt index 3cd76649cd..8e9babd7f2 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt @@ -118,18 +118,22 @@ internal class UpdateWalletManagerResultFactory { } private fun createTxHistoryItem(walletAddresses: Set, 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 + val isOutgoing = data.sourceAddress in walletAddresses return TxHistoryItem( txHash = hash, timestampInMillis = TimeUnit.SECONDS.toMillis(millis), - direction = direction, + isOutgoing = isOutgoing, + destinationType = TxHistoryItem.DestinationType.Single( + TxHistoryItem.AddressType.User(data.destinationAddress), + ), + sourceType = TxHistoryItem.SourceType.Single(data.sourceAddress), + interactionAddressType = TxHistoryItem.InteractionAddressType.User( + if (isOutgoing) data.destinationAddress else data.sourceAddress, + ), status = when (data.status) { TransactionStatus.Confirmed -> TxHistoryItem.TransactionStatus.Confirmed TransactionStatus.Unconfirmed -> TxHistoryItem.TransactionStatus.Unconfirmed @@ -139,35 +143,6 @@ internal class UpdateWalletManagerResultFactory { ) } - private fun extractDirection( - walletAddresses: Set, - 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.w( - """ - Unable to find transaction direction - |- To address: ${data.destinationAddress} - |- From address: ${data.sourceAddress} - |- Network addresses: $walletAddresses - """.trimIndent(), - ) - - return null - } - } - } - private fun getAvailableAddresses(addresses: Set
): Set { return addresses.mapTo(hashSetOf()) { it.value } } diff --git a/domain/txhistory/models/src/main/kotlin/com/tangem/domain/txhistory/models/TxHistoryItem.kt b/domain/txhistory/models/src/main/kotlin/com/tangem/domain/txhistory/models/TxHistoryItem.kt index b956574ce5..beaa4a031b 100644 --- a/domain/txhistory/models/src/main/kotlin/com/tangem/domain/txhistory/models/TxHistoryItem.kt +++ b/domain/txhistory/models/src/main/kotlin/com/tangem/domain/txhistory/models/TxHistoryItem.kt @@ -5,29 +5,39 @@ import java.math.BigDecimal data class TxHistoryItem( val txHash: String, val timestampInMillis: Long, - val direction: TransactionDirection, + val isOutgoing: Boolean, + val destinationType: DestinationType, + val sourceType: SourceType, + val interactionAddressType: InteractionAddressType, val status: TransactionStatus, val type: TransactionType, val amount: BigDecimal, ) { - sealed interface TransactionDirection { - val address: Address + sealed class DestinationType { + data class Single(val addressType: AddressType) : DestinationType() + data class Multiple(val addressTypes: List) : DestinationType() + } - data class Incoming(override val address: Address) : TransactionDirection - data class Outgoing(override val address: Address) : TransactionDirection + sealed class SourceType { + + data class Single(val address: String) : SourceType() + data class Multiple(val addresses: List) : SourceType() + } + + sealed class AddressType { + abstract val address: String + + data class User(override val address: String) : AddressType() + data class Contract(override val address: String) : AddressType() } 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 + object UnknownOperation : TransactionType + data class Operation(val name: String) : TransactionType } sealed class TransactionStatus { @@ -36,8 +46,9 @@ data class TxHistoryItem( object Confirmed : TransactionStatus() } - sealed class Address { - data class Single(val rawAddress: String) : Address() - object Multiple : Address() + sealed class InteractionAddressType { + data class User(val address: String) : InteractionAddressType() + data class Contract(val address: String) : InteractionAddressType() + data class Multiple(val addresses: List) : InteractionAddressType() } } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt index c0aead9837..40261aefd2 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt @@ -101,9 +101,7 @@ internal class TokenDetailsTxHistoryItemFlowConverter( ) { val txContent = txHistoryItemState.state as TransactionState.Content txHistoryItemState.copy( - state = txContent.copySealed( - timestamp = txContent.timestamp.toTimeFormat(), - ), + state = txContent.copy(timestamp = txContent.timestamp.toTimeFormat()), ) } else { txHistoryItemState diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt index 9425cf38e5..1d0fad1741 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt @@ -2,6 +2,9 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory. import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.utils.DateTimeFormatters import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents @@ -22,121 +25,65 @@ internal class TokenDetailsTxHistoryToTransactionStateConverter( return createTransactionStateItem(item = value) } - // TODO: Finalize transaction types [REDACTED_JIRA] - @Suppress("LongMethod") 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.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Deposit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Submit -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Submit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Supply -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Supply"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Unoswap"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Withdraw"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str(type.id), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + return TransactionState.Content( + txHash = item.txHash, + address = stringReference("mocked address"), + amount = item.getAmount(), + timestamp = item.timestampInMillis.toTimeFormat(), + status = item.status.tiUiStatus(), + direction = item.extractDirection(), + iconRes = item.extractIcon(), + title = item.extractTitle(), + subtitle = item.extractSubtitle(), + onClick = { clickIntents.onTransactionClick(item.txHash) }, + ) + } + + private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { + R.drawable.ic_close_24 + } else { + when (type) { + is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 + is TxHistoryItem.TransactionType.Operation, + is TxHistoryItem.TransactionType.Swap, + is TxHistoryItem.TransactionType.Transfer, + is TxHistoryItem.TransactionType.UnknownOperation, + -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 } } - private fun mapTransfer(item: TxHistoryItem): TransactionState { - return TransactionState.Transfer( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { + is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) + is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) + is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) + is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) + is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) } - private fun mapApprove(item: TxHistoryItem): TransactionState { - return TransactionState.Approve( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - private fun mapSwap(item: TxHistoryItem): TransactionState { - return TransactionState.Swap( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - - 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.extractSubtitle(): TextReference = + when (val interactionAddress = interactionAddressType) { + is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( + id = R.string.transaction_history_contract_address, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), + ) + is TxHistoryItem.InteractionAddressType.User -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + } private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed @@ -148,16 +95,11 @@ internal class TokenDetailsTxHistoryToTransactionStateConverter( return DateTimeFormatters.formatTime(time = DateTime(this, DateTimeZone.getDefault())) } - private fun TxHistoryItem.TransactionDirection.toUiDirection() = when (this) { - is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Content.Direction.INCOMING - is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Content.Direction.OUTGOING - } + private fun TxHistoryItem.extractDirection() = + if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING private fun TxHistoryItem.getAmount(): String { - val prefix = when (direction) { - is TxHistoryItem.TransactionDirection.Incoming -> "+" - is TxHistoryItem.TransactionDirection.Outgoing -> "-" - } + val prefix = if (isOutgoing) "-" else "+" return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) } } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt index 6690c6d52f..215e6a8c4f 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt @@ -1,7 +1,11 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory import com.tangem.core.ui.components.transactions.state.TransactionState +import com.tangem.core.ui.components.transactions.state.TransactionState.Content.Direction import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R @@ -19,116 +23,68 @@ internal class TokenDetailsTxHistoryTransactionStateConverter( return createTransactionStateItem(item = value) } - // TODO: Finalize transaction types [REDACTED_JIRA] @Suppress("LongMethod") 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.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Deposit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Submit -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Submit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Supply -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Supply"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Unoswap"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Withdraw"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str(type.id), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + return TransactionState.Content( + txHash = item.txHash, + address = stringReference("mocked address"), + amount = item.getAmount(), + timestamp = item.getRawTimestamp(), + status = item.status.tiUiStatus(), + direction = item.extractDirection(), + iconRes = item.extractIcon(), + title = item.extractTitle(), + subtitle = item.extractSubtitle(), + onClick = { clickIntents.onTransactionClick(item.txHash) }, + ) + } + + private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { + R.drawable.ic_close_24 + } else { + when (type) { + is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 + is TxHistoryItem.TransactionType.Operation, + is TxHistoryItem.TransactionType.Swap, + is TxHistoryItem.TransactionType.Transfer, + is TxHistoryItem.TransactionType.UnknownOperation, + -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 } } - private fun mapTransfer(item: TxHistoryItem): TransactionState { - return TransactionState.Transfer( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { + is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) + is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) + is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) + is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) + is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) } - private fun mapApprove(item: TxHistoryItem): TransactionState { - return TransactionState.Approve( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - private fun mapSwap(item: TxHistoryItem): TransactionState { - return TransactionState.Swap( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } + private fun TxHistoryItem.extractSubtitle(): TextReference = + when (val interactionAddress = interactionAddressType) { + is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( + id = R.string.transaction_history_contract_address, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), + ) + is TxHistoryItem.InteractionAddressType.User -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + } + + private fun TxHistoryItem.extractDirection() = if (isOutgoing) Direction.OUTGOING else Direction.INCOMING /** * Get timestamp without formatting. @@ -138,27 +94,14 @@ internal class TokenDetailsTxHistoryTransactionStateConverter( */ private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString() - 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 } - private fun TxHistoryItem.TransactionDirection.toUiDirection() = when (this) { - is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Content.Direction.INCOMING - is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Content.Direction.OUTGOING - } - private fun TxHistoryItem.getAmount(): String { - val prefix = when (direction) { - is TxHistoryItem.TransactionDirection.Incoming -> "+" - is TxHistoryItem.TransactionDirection.Outgoing -> "-" - } + val prefix = if (isOutgoing) "-" else "+" return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index 2c1bac9277..3e859f54c2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -9,6 +9,7 @@ import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.event.consumedEvent import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemColorPalette import com.tangem.domain.wallets.models.UserWalletId @@ -417,25 +418,31 @@ internal object WalletPreviewData { listOf( TxHistoryState.TxHistoryItemState.GroupTitle("Today"), TxHistoryState.TxHistoryItemState.Transaction( - TransactionState.Transfer( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "-0.500913 BTC", timestamp = "8:41", status = TransactionState.Content.Status.Unconfirmed, direction = TransactionState.Content.Direction.OUTGOING, + iconRes = com.tangem.core.ui.R.drawable.ic_arrow_up_24, + title = resourceReference(com.tangem.core.ui.R.string.common_transfer), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), ), TxHistoryState.TxHistoryItemState.GroupTitle("Yesterday"), TxHistoryState.TxHistoryItemState.Transaction( - TransactionState.Transfer( + TransactionState.Content( txHash = UUID.randomUUID().toString(), address = TextReference.Str("33BddS...ga2B"), amount = "-0.500913 BTC", timestamp = "8:41", status = TransactionState.Content.Status.Confirmed, direction = TransactionState.Content.Direction.OUTGOING, + iconRes = com.tangem.core.ui.R.drawable.ic_arrow_up_24, + title = resourceReference(com.tangem.core.ui.R.string.common_transfer), + subtitle = TextReference.Str("33BddS...ga2B"), onClick = {}, ), ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt index e8e5b65758..8f3e20271e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt @@ -109,9 +109,7 @@ internal class WalletTxHistoryItemFlowConverter( ) { val txContent = txHistoryItemState.state as TransactionState.Content txHistoryItemState.copy( - state = txContent.copySealed( - timestamp = txContent.timestamp.toTimeFormat(), - ), + state = txContent.copy(timestamp = txContent.timestamp.toTimeFormat()), ) } else { txHistoryItemState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt index b43fbb3029..9772f07b58 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt @@ -2,6 +2,9 @@ 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.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents @@ -19,116 +22,69 @@ internal class WalletTxHistoryTransactionStateConverter( return createTransactionStateItem(item = value) } - // TODO: Finalize transaction types [REDACTED_JIRA] @Suppress("LongMethod") 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.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Deposit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Submit -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Submit"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Supply -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Supply"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Unoswap"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str("Withdraw"), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - title = TextReference.Str(type.id), - subtitle = item.direction.extractAddress(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + return TransactionState.Content( + txHash = item.txHash, + address = stringReference("mocked address"), + amount = item.getAmount(), + timestamp = item.getRawTimestamp(), + status = item.status.tiUiStatus(), + direction = item.extractDirection(), + iconRes = item.extractIcon(), + title = item.extractTitle(), + subtitle = item.extractSubtitle(), + onClick = { clickIntents.onTransactionClick(item.txHash) }, + ) + } + + private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { + R.drawable.ic_close_24 + } else { + when (type) { + is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 + is TxHistoryItem.TransactionType.Operation, + is TxHistoryItem.TransactionType.Swap, + is TxHistoryItem.TransactionType.Transfer, + is TxHistoryItem.TransactionType.UnknownOperation, + -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 } } - private fun mapTransfer(item: TxHistoryItem): TransactionState { - return TransactionState.Transfer( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) + private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { + is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) + is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) + is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) + is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) + is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) } - private fun mapApprove(item: TxHistoryItem): TransactionState { - return TransactionState.Approve( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - private fun mapSwap(item: TxHistoryItem): TransactionState { - return TransactionState.Swap( - txHash = item.txHash, - address = item.direction.extractAddress(), - amount = item.getAmount(), - timestamp = item.getRawTimestamp(), - status = item.status.tiUiStatus(), - direction = item.direction.toUiDirection(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } + private fun TxHistoryItem.extractSubtitle(): TextReference = + when (val interactionAddress = interactionAddressType) { + is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( + id = R.string.transaction_history_contract_address, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), + ) + is TxHistoryItem.InteractionAddressType.User -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + } + + private fun TxHistoryItem.extractDirection() = + if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING /** * Get timestamp without formatting. @@ -138,27 +94,14 @@ internal class WalletTxHistoryTransactionStateConverter( */ private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString() - 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 } - private fun TxHistoryItem.TransactionDirection.toUiDirection() = when (this) { - is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Content.Direction.INCOMING - is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Content.Direction.OUTGOING - } - private fun TxHistoryItem.getAmount(): String { - val prefix = when (direction) { - is TxHistoryItem.TransactionDirection.Incoming -> "+" - is TxHistoryItem.TransactionDirection.Outgoing -> "-" - } + val prefix = if (isOutgoing) "-" else "+" return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) } } \ No newline at end of file diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 62477a6c9c..eb1c0ab71a 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -83,8 +83,8 @@ spr-client = "3.6.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.0-363" -#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds +#tangemBlockchainSdk = "release-app_5.0-363" +tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.0-308" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds # endregion Tangem