diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 95bfe4d9e6..58da791e4e 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -583,7 +583,6 @@ Zuerst die Sicherung abschließen Unvollständig Andere Methoden - Physische Geräte, die Deine privaten Schlüssel sicher offline speichern. Wiederherstellungs-Phrase Um Deine Wallet auf Hardware umzustellen, erstelle vorher ein Backup. Deine privaten Schlüssel sind sicher verschlüsselt und auf Deinem Telefon gespeichert. diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index b15a7f50b0..3979991fb5 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -3,6 +3,10 @@ アクセスコードがないとウォレットは安全ではありません。 とにかくスキップ アクセスコードが設定されていません + コードを変更 + アクセスコードは、ウォレットのロック解除・資産へのアクセス保護に使用されます + このまま使用 + このアクセスコードは簡単に推測される可能性があります アクセスコードを入力 アクセスコードが間違っています。あと%s回間違えると、モバイルウォレットが削除されます。 アクセスコードが間違っています。あと%s回失敗すると、アプリはロックされます。 @@ -586,7 +590,6 @@ まずバックアップを完了する まずバックアップを完了する その他の方法 - 秘密鍵をオフラインで安全に保存する物理デバイス。 リカバリーフレーズ アクセスコードを使用してウォレットを保護するには、まずバックアップを完了してください。 ウォレットをハードウェアにアップグレードするには、まずバックアップしてください。 @@ -773,6 +776,10 @@ 取引量 これをドラッグするか、検索窓をタップして、マーケットから直接トークンを追加します トークンを追加 + 資産を即時アクセス可能な状態に保ったまま、パワーアップさせよう。%s + 利息モードを有効にする + モバイルウォレットを作成するには、%1$sにアップデートする必要があります + モバイルウォレットを使用するには、%1$s以降が必要です すべてのニュース 最新情報を入手 お使いのデバイスではNFCが使用できません @@ -1897,6 +1904,7 @@ Tangemは、生成された利息に対して15%サービス手数料も徴収します。 ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。 過去のリターン + 保有資産に年利%1$s%%を適用 利息モードでのトークンの承認が取り消されました。トークンを開いて再度許可してください。 トークンの承認が必要です ネットワーク接続を確認してください @@ -1911,7 +1919,9 @@ 分散型・自己管理型 このサービスを利用することにより、プロバイダー\n%1$sおよび%2$sに同意するものとします。 Aaveに接続 + 残高に %1$s%% の年利(APY)を適用 Aave %1$s%% • 変動金利 + 変動金利 Aave 平均%s 昨年のリターン @@ -1938,12 +1948,16 @@ 利息モード 利息モードの有効化 利息モード - 利息モードが有効になりました + 利息モードコントラクトのデプロイ + 利息モードを有効にする %1$sがAaveに供給されました - 利息モードが無効になりました + 利息モードを無効にする %1$sがAaveから引き出されました + 利息モードをセットアップ + 利息モードの再有効化 Aaveへの供給 %1$sがAaveに供給されました + Aaveから引き出す 自動 取引のネットワーク手数料をカバーするために、 %1$s %2$sを追加してください。 %s手数料を支払えません diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index db0fefa23f..62446f8321 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -274,7 +274,7 @@ Из Из %s Синхронизировать адреса - Начать зарабатывать + Начать Получить токен К провайдеру Перейти в токен @@ -576,7 +576,7 @@ Сначала завершите создание резервной копии Не завершено Другие способы - Физические устройства, которые надёжно хранят ваш приватный ключ офлайн. + Сохраните свою recovery-фразу вручную в надёжном месте. Держите её в секрете, чтобы защитить свои средства. Фраза восстановления Чтобы защитить ваш кошелёк с помощью кода доступа, сначала завершите резервное копирование. Чтобы улучшить кошелёк до аппаратного, сначала создайте резервную копию. @@ -1075,7 +1075,7 @@ Обратите внимание, что для совершения транзакции с вашими средствами по-прежнему потребуется ваша карта или кольцо Сканировать Отсканируйте карту или кольцо, чтобы изменить ее настройки. Изменения затронут только ту карту или кольцо, которые вы отсканировали, и не повлияют на другие устройства, привязанные к вашему кошельку. - Приготовьте свой Tangem! + Приготовьте устройство Tangem! Уведомление безопасности Нет Да @@ -1538,6 +1538,7 @@ Восстановите существующий кошелек через Google Drive. Импорт из Google Drive Добавить существующий кошелек + Физические устройства, которые безопасно хранят ваш приватный ключ офлайн. Сканировать кошелек Tangem Импортируйте существующий кошелек через вашу фразу восстановления. Имрортировать кошелек @@ -1854,9 +1855,9 @@ Режим доходности Включение режима доходности Режим доходности - Режим доходности включен + Включение режима доходности %1$s отправлено в Aave - Режим доходности выключен + Отключение режима доходности %1$s выведено из Aave Перевод средств в Aave %1$s отправлено в Aave diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index deea678229..1dd7761587 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -3,6 +3,10 @@ Without an access code, your wallet is not secure. Skip anyway Access code not set + Change code + Your access code will be used to unlock your wallet and to protect access to the assets + Use anyway + This access code can be easily guessed Enter access code Wrong access code. Your mobile wallet will be deleted after %s more incorrect attempts. Wrong access code. The app will be locked after %s more failed attempts @@ -596,7 +600,7 @@ Finalize backup first Incomplete Other methods - Physical devices that securely store your private key offline. + Manually save your recovery phrase in a secure place and keep it private to protect your funds. Recovery phrase To secure your wallet with a Access Code, complete the backup first. To upgrade your wallet to hardware, back it up first. @@ -788,6 +792,10 @@ Volume Pull this up or tap the search bar to add tokens directly from the market Add tokens + Power up your assets while supplying them with instant access. %s + Activate Yield Mode + You must update to %1$s in order to create mobile wallet + Mobile Wallet requires %1$s or later All news Stay in the loop NFC is not available on your device @@ -1450,6 +1458,8 @@ Failed to issue card A technical error has occurred, please try again by clicking the button below. A technical error has occurred, please contact support. + Use your crypto for real world spending. \nIt\'s a payment card unlike any other. + Get Tangem Pay It usually takes up to 15 minutes Setting up your Tangem Card Issuing your card @@ -1474,6 +1484,7 @@ Service temporarily unavailable The service is currently unreachable. Please try again later. Sync needed + Tangem Visa Card Tangem Pay is temporarily unavailable Tangem Pay Use your card or ring to restore access to your payment account @@ -1520,6 +1531,7 @@ 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 + for: %s from: %s to: %s validator: %s @@ -1973,6 +1985,7 @@ Tangem also takes a 15% service fee on yield generated. Your funds will be automatically supplied to Aave once network fees are lower or your balance meets the minimum required amount. Historical returns + "Enable %1$s%% APY on your balance" Approval for your token in Yield Mode has been revoked. Open the token to grant permission again. Token approval needed Check your network connection @@ -2016,12 +2029,16 @@ Yield Mode Enabling Yield Mode Yield Mode - Yield Mode enabled + Yield Mode contract deploy + Yield Mode enable %1$s supplied to Aave - Yield Mode disabled + Yield Mode disable %1$s withdrawn from Aave + Yield Mode initialize + Yield Mode reactivate Supply to Aave %1$s supplied to Aave + Withdraw from Aave Automatic Add some %1$s %2$s to cover the network fee for transactions. Unable to cover %s fee 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 53ec6c23b8..884b8bfdae 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 @@ -19,10 +19,12 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ChainStyle import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import androidx.constraintlayout.compose.Visibility +import androidx.constraintlayout.compose.atLeast import com.tangem.core.ui.R import com.tangem.core.ui.components.CircleShimmer import com.tangem.core.ui.components.RectangleShimmer @@ -94,7 +96,7 @@ fun Transaction(state: TransactionState, isBalanceHidden: Boolean, modifier: Mod bottom.linkTo(subtitleItem.top) start.linkTo(iconItem.end) end.linkTo(amountItem.start) - width = Dimension.fillToConstraints + width = Dimension.fillToConstraints.atLeast(50.dp) }, ) @@ -122,7 +124,6 @@ fun Transaction(state: TransactionState, isBalanceHidden: Boolean, modifier: Mod visibility = state.isGoneIf { amount.isEmpty() } top.linkTo(parent.top) bottom.linkTo(timestampItem.top) - start.linkTo(titleItem.end) end.linkTo(parent.end) width = Dimension.fillToConstraints }, @@ -436,7 +437,7 @@ private class TransactionItemStateProvider : CollectionPreviewParameterProvider< ), TransactionState.Content( txHash = UUID.randomUUID().toString(), - amount = "0.625 USDT", + amount = "0.62521313 USDT", time = "€0.50", status = Status.Confirmed, direction = Direction.OUTGOING, diff --git a/core/ui/src/main/res/drawable/ic_connect_24.xml b/core/ui/src/main/res/drawable/ic_connect_24.xml new file mode 100644 index 0000000000..ebab5fcf69 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_connect_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_disconnect_24.xml b/core/ui/src/main/res/drawable/ic_disconnect_24.xml new file mode 100644 index 0000000000..2baf3ca1c9 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_disconnect_24.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/core/ui/src/main/res/drawable/ic_gear_24.xml b/core/ui/src/main/res/drawable/ic_gear_24.xml new file mode 100644 index 0000000000..ea7f21abb2 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_gear_24.xml @@ -0,0 +1,14 @@ + + + + diff --git a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionHistoryItemConverter.kt b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionHistoryItemConverter.kt index 40e874e14e..1a677b9cdb 100644 --- a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionHistoryItemConverter.kt +++ b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionHistoryItemConverter.kt @@ -24,7 +24,7 @@ internal class SdkTransactionHistoryItemConverter( SdkTransactionHistoryItem.TransactionStatus.Failed -> TxInfo.TransactionStatus.Failed SdkTransactionHistoryItem.TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed }, - type = typeConverter.convert(value.type), + type = typeConverter.convert(value.type to value.destinationType.toDomain()), amount = requireNotNull(value.amount.value) { "Transaction amount value must not be null" }, ) diff --git a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionTypeConverter.kt b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionTypeConverter.kt index 7e674c1f59..5e9fe1dc0b 100644 --- a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionTypeConverter.kt +++ b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/SdkTransactionTypeConverter.kt @@ -1,21 +1,27 @@ package com.tangem.data.walletmanager.utils import com.tangem.blockchain.transactionhistory.models.TransactionHistoryItem.TransactionType +import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData +import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyExitCallData +import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyInitTokenCallData +import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyReactivateTokenCallData import com.tangem.domain.models.network.TxInfo import com.tangem.domain.walletmanager.model.SmartContractMethod import com.tangem.utils.converter.Converter internal class SdkTransactionTypeConverter( private val smartContractMethods: Map, -) : Converter { +) : Converter, TxInfo.TransactionType> { - override fun convert(value: TransactionType): TxInfo.TransactionType { - return when (value) { + override fun convert(value: Pair): TxInfo.TransactionType { + val (type, destination) = value + + return when (type) { is TransactionType.ContractMethod -> { - getTransactionType(methodName = smartContractMethods[value.id]?.name) + getTransactionType(methodName = smartContractMethods[type.id]?.name, type.callData, destination) } is TransactionType.ContractMethodName -> { - getTransactionType(methodName = value.name) + getTransactionType(methodName = type.name, type.callData, destination) } is TransactionType.Transfer -> { TxInfo.TransactionType.Transfer @@ -27,7 +33,7 @@ internal class SdkTransactionTypeConverter( TxInfo.TransactionType.Staking.Unstake } is TransactionType.TronStakingTransactionType.VoteWitnessContract -> { - TxInfo.TransactionType.Staking.Vote(value.validatorAddress) + TxInfo.TransactionType.Staking.Vote(type.validatorAddress) } is TransactionType.TronStakingTransactionType.WithdrawBalanceContract -> { TxInfo.TransactionType.Staking.ClaimRewards @@ -38,7 +44,12 @@ internal class SdkTransactionTypeConverter( } } - private fun getTransactionType(methodName: String?): TxInfo.TransactionType { + @Suppress("CyclomaticComplexMethod") + private fun getTransactionType( + methodName: String?, + callData: String?, + destination: TxInfo.DestinationType, + ): TxInfo.TransactionType { return when (methodName) { "transfer" -> TxInfo.TransactionType.Transfer "approve" -> TxInfo.TransactionType.Approve @@ -59,11 +70,33 @@ internal class SdkTransactionTypeConverter( "withdrawRewardsPOL", -> TxInfo.TransactionType.Staking.ClaimRewards "redelegate" -> TxInfo.TransactionType.Staking.Restake - "supplyEnter" -> TxInfo.TransactionType.YieldSupply.Enter - "supplyExit" -> TxInfo.TransactionType.YieldSupply.Exit + "yieldSend" -> TxInfo.TransactionType.YieldSupply.Send + "enterProtocolByOwner" -> callData?.let { data -> + TxInfo.TransactionType.YieldSupply.Enter( + EthereumYieldSupplyEnterCallData.decode(data)?.tokenContractAddress.orEmpty(), + ) + } + "withdrawAndDeactivate" -> callData?.let { data -> + TxInfo.TransactionType.YieldSupply.Exit( + EthereumYieldSupplyExitCallData.decode(data)?.tokenContractAddress.orEmpty(), + ) + } + "deployYieldModule" -> TxInfo.TransactionType.YieldSupply.DeployContract( + (destination as? TxInfo.DestinationType.Single)?.addressType?.address.orEmpty(), + ) + "initYieldToken" -> callData?.let { data -> + TxInfo.TransactionType.YieldSupply.InitializeToken( + EthereumYieldSupplyInitTokenCallData.decode(data)?.tokenContractAddress.orEmpty(), + ) + } + "reactivateToken" -> callData?.let { data -> + TxInfo.TransactionType.YieldSupply.ReactivateToken( + EthereumYieldSupplyReactivateTokenCallData.decode(data)?.tokenContractAddress.orEmpty(), + ) + } "supplyTopUp" -> TxInfo.TransactionType.YieldSupply.Topup null -> TxInfo.TransactionType.UnknownOperation else -> TxInfo.TransactionType.Operation(name = methodName.replaceFirstChar { it.titlecase() }) - } + } ?: TxInfo.TransactionType.Operation(name = methodName?.replaceFirstChar { it.titlecase() }.orEmpty()) } } \ No newline at end of file diff --git a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/TransactionDataToTxHistoryItemConverter.kt b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/TransactionDataToTxHistoryItemConverter.kt index dae65d3ec7..36016b121b 100644 --- a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/TransactionDataToTxHistoryItemConverter.kt +++ b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/utils/TransactionDataToTxHistoryItemConverter.kt @@ -45,7 +45,7 @@ internal class TransactionDataToTxHistoryItemConverter( TransactionStatus.Confirmed -> TxInfo.TransactionStatus.Confirmed TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed }, - type = getTransactionType(value.extras), + type = getTransactionType(value), amount = amount, ) } @@ -99,16 +99,25 @@ internal class TransactionDataToTxHistoryItemConverter( ) } - private fun getTransactionType(extras: TransactionExtras?): TxInfo.TransactionType { - return when (extras) { + private fun getTransactionType(transactionData: TransactionData.Uncompiled?): TxInfo.TransactionType { + return when (val extras = transactionData?.extras) { is EthereumTransactionExtras -> { - when (extras.callData) { - is EthereumYieldSupplyDeployCallData, - is EthereumYieldSupplyReactivateTokenCallData, - is EthereumYieldSupplyInitTokenCallData, - is EthereumYieldSupplyEnterCallData, - -> TxInfo.TransactionType.YieldSupply.Enter - is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit + when (val callData = extras.callData) { + is EthereumYieldSupplyDeployCallData -> TxInfo.TransactionType.YieldSupply.DeployContract( + transactionData.destinationAddress, + ) + is EthereumYieldSupplyReactivateTokenCallData -> TxInfo.TransactionType.YieldSupply.ReactivateToken( + callData.tokenContractAddress, + ) + is EthereumYieldSupplyInitTokenCallData -> TxInfo.TransactionType.YieldSupply.InitializeToken( + callData.tokenContractAddress, + ) + is EthereumYieldSupplyEnterCallData -> TxInfo.TransactionType.YieldSupply.Enter( + callData.tokenContractAddress, + ) + is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit( + callData.tokenContractAddress, + ) is ApprovalERC20TokenCallData -> TxInfo.TransactionType.Approve else -> TxInfo.TransactionType.Transfer } diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt index e652292644..384cb82f4b 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt @@ -174,10 +174,10 @@ internal class DefaultYieldSupplyRepository( null } - private fun Set.hasYieldEnterTransactions(yieldAddress: String) = any { - it.type == TxInfo.TransactionType.YieldSupply.Enter || - it.type == TxInfo.TransactionType.Approve && - (it.interactionAddressType as? TxInfo.InteractionAddressType.Contract)?.address == yieldAddress + private fun Set.hasYieldEnterTransactions(yieldAddress: String) = any { txInfo -> + txInfo.type is TxInfo.TransactionType.YieldSupply.Enter || + txInfo.type == TxInfo.TransactionType.Approve && + (txInfo.interactionAddressType as? TxInfo.InteractionAddressType.Contract)?.address == yieldAddress } private fun Set.hasYieldExitTransactions() = any { diff --git a/domain/legacy/src/main/assets/contract_methods.json b/domain/legacy/src/main/assets/contract_methods.json index 5ca94cd491..fe538d3526 100644 --- a/domain/legacy/src/main/assets/contract_methods.json +++ b/domain/legacy/src/main/assets/contract_methods.json @@ -205,32 +205,32 @@ "0xcbeda14c": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "supply" + "name": "deployYieldModule" }, "0x79be55f7": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "supplyEnter" + "name": "enterProtocolByOwner" }, "0xc65e6dcf": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "supplyExit" + "name": "withdrawAndDeactivate" }, "0xebd4b81c": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "supply" + "name": "initYieldToken" }, "0xc478e956": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "supply" + "name": "reactivateToken" }, "0x0779afe6": { "info": "yieldModule", "source": "https://github.com/tangem/tangem-yield-module-contracts/", - "name": "transfer" + "name": "yieldSend" }, "0xb9de6a93": { "info": "yieldModule", diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/network/TxInfo.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/network/TxInfo.kt index 65467f7460..d8fd074625 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/network/TxInfo.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/network/TxInfo.kt @@ -110,14 +110,32 @@ data class TxInfo( @Serializable sealed interface YieldSupply : TransactionType { - @Serializable - data object Enter : YieldSupply + val address: String? @Serializable - data object Exit : YieldSupply + data class Enter(override val address: String) : YieldSupply @Serializable - data object Topup : YieldSupply + data class Exit(override val address: String) : YieldSupply + + @Serializable + data object Topup : YieldSupply { + override val address: String? = null + } + + @Serializable + data object Send : YieldSupply { + override val address: String? = null + } + + @Serializable + data class DeployContract(override val address: String) : YieldSupply + + @Serializable + data class ReactivateToken(override val address: String) : YieldSupply + + @Serializable + data class InitializeToken(override val address: String) : YieldSupply } @Serializable diff --git a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt index 0fc75e0d67..bc5f160b47 100644 --- a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt +++ b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt @@ -41,7 +41,9 @@ internal class TxHistoryItemToTransactionStateConverter( R.drawable.ic_close_24 } else { when (type) { - is TransactionType.Approve -> R.drawable.ic_doc_24 + is TransactionType.YieldSupply.DeployContract, + is TransactionType.Approve, + -> R.drawable.ic_doc_24 is TransactionType.Staking.Stake, is TransactionType.Staking.Vote, is TransactionType.Staking.Restake, @@ -51,11 +53,16 @@ internal class TxHistoryItemToTransactionStateConverter( is TransactionType.Staking.Unstake, is TransactionType.Staking.Withdraw, -> R.drawable.ic_transaction_history_unstaking_24 + is TransactionType.YieldSupply.Enter -> R.drawable.ic_connect_24 + is TransactionType.YieldSupply.InitializeToken -> R.drawable.ic_gear_24 + is TransactionType.YieldSupply.ReactivateToken -> R.drawable.ic_refresh_24 + is TransactionType.YieldSupply.Exit -> R.drawable.ic_disconnect_24 is TransactionType.Operation, is TransactionType.Swap, is TransactionType.Transfer, - is TransactionType.YieldSupply, is TransactionType.UnknownOperation, + TransactionType.YieldSupply.Send, + TransactionType.YieldSupply.Topup, -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 } } @@ -66,32 +73,76 @@ internal class TxHistoryItemToTransactionStateConverter( is TransactionType.Operation -> stringReference(type.name) is TransactionType.Swap -> resourceReference(R.string.common_swap) is TransactionType.Transfer -> resourceReference(R.string.common_transfer) - is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter) - is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit) - is TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup) is TransactionType.Staking.Stake -> resourceReference(R.string.common_stake) is TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake) is TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote) is TransactionType.Staking.ClaimRewards -> resourceReference(R.string.common_claim_rewards) is TransactionType.Staking.Withdraw -> resourceReference(R.string.staking_withdraw) is TransactionType.Staking.Restake -> resourceReference(R.string.staking_restake) + is TransactionType.YieldSupply -> when (type) { + is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter) + is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit) + TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup) + TransactionType.YieldSupply.Send -> if (isOutgoing) { + resourceReference(R.string.common_transfer) + } else { + resourceReference(R.string.yield_module_transaction_withdraw) + } + is TransactionType.YieldSupply.DeployContract -> resourceReference( + R.string + .yield_module_transaction_deploy_contract, + ) + is TransactionType.YieldSupply.InitializeToken -> resourceReference( + R.string + .yield_module_transaction_initialize, + ) + is TransactionType.YieldSupply.ReactivateToken -> resourceReference( + R.string + .yield_module_transaction_reactivate, + ) + } is TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) } private fun TxInfo.extractSubtitle(): TextReference { - return when (this.type) { - is TransactionType.YieldSupply.Enter -> { - val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } - resourceReference(R.string.yield_module_transaction_enter_subtitle, wrappedList(amount)) - } - is TransactionType.YieldSupply.Topup, - -> { - val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } - resourceReference(R.string.yield_module_transaction_topup_subtitle, wrappedList(amount)) - } - is TransactionType.YieldSupply.Exit -> { - val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } - resourceReference(R.string.yield_module_transaction_exit_subtitle, wrappedList(amount)) + return when (val type = this.type) { + is TransactionType.YieldSupply -> if (currency is CryptoCurrency.Coin) { + if (type == TransactionType.YieldSupply.Send) { + extractSubtitleByAddressType() + } else { + resourceReference( + R.string.transaction_history_transaction_for_address, + wrappedList(type.address?.toBriefAddressFormat().orEmpty()), + ) + } + } else { + when (type) { + is TransactionType.YieldSupply.Enter -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference(R.string.yield_module_transaction_enter_subtitle, wrappedList(amount)) + } + TransactionType.YieldSupply.Topup -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference(R.string.yield_module_transaction_topup_subtitle, wrappedList(amount)) + } + is TransactionType.YieldSupply.Exit -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference(R.string.yield_module_transaction_exit_subtitle, wrappedList(amount)) + } + TransactionType.YieldSupply.Send -> { + if (isOutgoing) { + extractSubtitleByAddressType() + } else { + val amount = + amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference( + R.string.yield_module_transaction_exit_subtitle, + wrappedList(amount), + ) + } + } + else -> extractSubtitleByAddressType() + } } else -> extractSubtitleByAddressType() } @@ -133,14 +184,21 @@ internal class TxHistoryItemToTransactionStateConverter( @Suppress("ComplexCondition") private fun TxInfo.getAmount(): String { - if (type is TransactionType.Staking.Vote || - type == TransactionType.Staking.ClaimRewards || - type == TransactionType.Staking.Withdraw || - type == TransactionType.YieldSupply.Enter || - type == TransactionType.YieldSupply.Exit || - type == TransactionType.YieldSupply.Topup - ) { - return "" + when (type) { + is TransactionType.Staking.Vote, + TransactionType.Staking.ClaimRewards, + TransactionType.Staking.Withdraw, + -> return "" + + is TransactionType.YieldSupply -> if (currency is CryptoCurrency.Token) { + when (type) { + TransactionType.YieldSupply.Send -> if (!isOutgoing) { + return "" + } + else -> return "" + } + } + else -> Unit } val prefix = when { status == TxInfo.TransactionStatus.Failed -> "" diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt index 3b5dfff91c..fa92bb7623 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt @@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers import com.tangem.blockchain.common.Blockchain import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.TxInfo import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.domain.models.wallet.UserWallet @@ -17,6 +18,7 @@ internal class SetTxHistoryCountErrorTransformer( private val error: TxHistoryStateError, private val pendingTransactions: Set, private val clickIntents: WalletClickIntents, + private val currency: CryptoCurrency, ) : WalletStateTransformer(userWallet.walletId) { private val txHistoryItemConverter by lazy { @@ -26,6 +28,7 @@ internal class SetTxHistoryCountErrorTransformer( } TxHistoryItemStateConverter( + currency = currency, symbol = blockchain.currency, decimals = blockchain.decimals(), clickIntents = clickIntents, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt index db435626e8..a30612c67e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt @@ -9,6 +9,7 @@ import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.utils.toTimeFormat +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.TxInfo import com.tangem.domain.models.network.TxInfo.TransactionStatus import com.tangem.domain.models.network.TxInfo.TransactionType @@ -20,6 +21,7 @@ import com.tangem.utils.converter.Converter import com.tangem.utils.toBriefAddressFormat internal class TxHistoryItemStateConverter( + private val currency: CryptoCurrency, private val symbol: String, private val decimals: Int, private val clickIntents: WalletClickIntents, @@ -49,7 +51,9 @@ internal class TxHistoryItemStateConverter( R.drawable.ic_close_24 } else { when (type) { - is TransactionType.Approve -> R.drawable.ic_doc_24 + is TransactionType.YieldSupply.DeployContract, + is TransactionType.Approve, + -> R.drawable.ic_doc_24 is TransactionType.Staking.Stake, is TransactionType.Staking.Vote, is TransactionType.Staking.Restake, @@ -59,11 +63,16 @@ internal class TxHistoryItemStateConverter( is TransactionType.Staking.Unstake, is TransactionType.Staking.Withdraw, -> R.drawable.ic_transaction_history_unstaking_24 + is TransactionType.YieldSupply.Enter -> R.drawable.ic_connect_24 + is TransactionType.YieldSupply.InitializeToken -> R.drawable.ic_gear_24 + is TransactionType.YieldSupply.ReactivateToken -> R.drawable.ic_refresh_24 + is TransactionType.YieldSupply.Exit -> R.drawable.ic_disconnect_24 is TransactionType.Operation, is TransactionType.Swap, is TransactionType.Transfer, - is TransactionType.YieldSupply, is TransactionType.UnknownOperation, + TransactionType.YieldSupply.Send, + TransactionType.YieldSupply.Topup, -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 } } @@ -74,32 +83,81 @@ internal class TxHistoryItemStateConverter( is TransactionType.Operation -> stringReference(type.name) is TransactionType.Swap -> resourceReference(R.string.common_swap) is TransactionType.Transfer -> resourceReference(R.string.common_transfer) - is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter) - is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit) - is TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup) is TransactionType.Staking.Stake -> resourceReference(R.string.common_stake) is TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake) is TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote) is TransactionType.Staking.ClaimRewards -> resourceReference(R.string.common_claim_rewards) is TransactionType.Staking.Withdraw -> resourceReference(R.string.staking_withdraw) is TransactionType.Staking.Restake -> resourceReference(R.string.staking_restake) + is TransactionType.YieldSupply -> when (type) { + is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter) + is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit) + TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup) + TransactionType.YieldSupply.Send -> if (isOutgoing) { + resourceReference(R.string.common_transfer) + } else { + resourceReference(R.string.yield_module_transaction_withdraw) + } + is TransactionType.YieldSupply.DeployContract -> resourceReference( + R.string + .yield_module_transaction_deploy_contract, + ) + is TransactionType.YieldSupply.InitializeToken -> resourceReference( + R.string + .yield_module_transaction_initialize, + ) + is TransactionType.YieldSupply.ReactivateToken -> resourceReference( + R.string + .yield_module_transaction_reactivate, + ) + } is TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) } private fun TxInfo.extractSubtitle(): TextReference { - return when (this.type) { - is TransactionType.YieldSupply.Enter -> { - val amount = amount.format { crypto(symbol = symbol, decimals = decimals) } - resourceReference(R.string.yield_module_transaction_enter_subtitle, wrappedList(amount)) - } - is TransactionType.YieldSupply.Topup, - -> { - val amount = amount.format { crypto(symbol = symbol, decimals = decimals) } - resourceReference(R.string.yield_module_transaction_topup_subtitle, wrappedList(amount)) - } - is TransactionType.YieldSupply.Exit -> { - val amount = amount.format { crypto(symbol = symbol, decimals = decimals) } - resourceReference(R.string.yield_module_transaction_exit_subtitle, wrappedList(amount)) + return when (val type = this.type) { + is TransactionType.YieldSupply -> if (currency is CryptoCurrency.Coin) { + resourceReference( + R.string.transaction_history_transaction_for_address, + wrappedList(type.address?.toBriefAddressFormat().orEmpty()), + ) + } else { + when (type) { + is TransactionType.YieldSupply.Enter -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference( + R.string.yield_module_transaction_enter_subtitle, + wrappedList(amount), + ) + } + TransactionType.YieldSupply.Topup -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference( + R.string.yield_module_transaction_topup_subtitle, + wrappedList(amount), + ) + } + TransactionType.YieldSupply.Send -> { + if (isOutgoing) { + extractSubtitleByAddressType() + } else { + val amount = + amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference( + R.string.yield_module_transaction_exit_subtitle, + wrappedList(amount), + ) + } + } + is TransactionType.YieldSupply.Exit -> { + val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) } + resourceReference( + R.string.yield_module_transaction_exit_subtitle, + wrappedList(amount), + ) + } + else -> extractSubtitleByAddressType() + } } else -> extractSubtitleByAddressType() } @@ -147,14 +205,18 @@ internal class TxHistoryItemStateConverter( @Suppress("ComplexCondition") private fun TxInfo.getAmount(): String { - if (type is TransactionType.Staking.Vote || - type == TransactionType.Staking.ClaimRewards || - type == TransactionType.Staking.Withdraw || - type == TransactionType.YieldSupply.Enter || - type == TransactionType.YieldSupply.Exit || - type == TransactionType.YieldSupply.Topup - ) { - return "" + when (type) { + is TransactionType.Staking.Vote, + TransactionType.Staking.ClaimRewards, + TransactionType.Staking.Withdraw, + -> return "" + + is TransactionType.YieldSupply -> { + if (currency is CryptoCurrency.Token && type == TransactionType.YieldSupply.Send && !isOutgoing) { + return "" + } + } + else -> Unit } val prefix = when { status == TransactionStatus.Failed -> "" diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt index b9c65f6340..bef7b6defb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt @@ -5,6 +5,7 @@ import androidx.paging.cachedIn import androidx.paging.map import arrow.core.Either import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.TxInfo import com.tangem.domain.models.wallet.UserWallet @@ -58,7 +59,7 @@ internal class TxHistorySubscriber( refresh = isRefresh, ).map { it.cachedIn(coroutineScope) } - setLoadedTxHistoryState(maybeTxHistoryItems) + setLoadedTxHistoryState(maybeTxHistoryItems, status.currency) } } } @@ -67,18 +68,19 @@ internal class TxHistorySubscriber( private fun setLoadingTxHistoryState(maybeTxHistoryItemCount: MaybeTxHistoryCount, status: CryptoCurrencyStatus) { stateHolder.update( maybeTxHistoryItemCount.fold( - ifLeft = { + ifLeft = { error -> SetTxHistoryCountErrorTransformer( userWallet = userWallet, - error = it, + error = error, pendingTransactions = status.value.pendingTransactions, + currency = status.currency, clickIntents = clickIntents, ) }, - ifRight = { + ifRight = { txCount -> SetTxHistoryCountTransformer( userWalletId = userWallet.walletId, - transactionsCount = it, + transactionsCount = txCount, clickIntents = clickIntents, ) }, @@ -86,7 +88,7 @@ internal class TxHistorySubscriber( ) } - private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems) { + private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems, currency: CryptoCurrency) { stateHolder.update( maybeTxHistoryItems.fold( ifLeft = { @@ -102,6 +104,7 @@ internal class TxHistorySubscriber( symbol = blockchain.currency, decimals = blockchain.decimals(), clickIntents = clickIntents, + currency = currency, ) SetTxHistoryItemsTransformer( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriberV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriberV2.kt index 23e7c78681..78c388f87f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriberV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriberV2.kt @@ -5,6 +5,7 @@ import androidx.paging.cachedIn import androidx.paging.map import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.TxInfo import com.tangem.domain.models.wallet.UserWallet @@ -51,7 +52,7 @@ internal class TxHistorySubscriberV2( refresh = isRefresh, ).map { it.cachedIn(coroutineScope) } - setLoadedTxHistoryState(maybeTxHistoryItems) + setLoadedTxHistoryState(maybeTxHistoryItems, currency = status.currency) } } } @@ -60,18 +61,19 @@ internal class TxHistorySubscriberV2( private fun setLoadingTxHistoryState(maybeTxHistoryItemCount: MaybeTxHistoryCount, status: CryptoCurrencyStatus) { stateController.update( maybeTxHistoryItemCount.fold( - ifLeft = { + ifLeft = { error -> SetTxHistoryCountErrorTransformer( userWallet = userWallet, - error = it, + error = error, pendingTransactions = status.value.pendingTransactions, clickIntents = clickIntents, + currency = status.currency, ) }, - ifRight = { + ifRight = { txCount -> SetTxHistoryCountTransformer( userWalletId = userWallet.walletId, - transactionsCount = it, + transactionsCount = txCount, clickIntents = clickIntents, ) }, @@ -79,7 +81,7 @@ internal class TxHistorySubscriberV2( ) } - private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems) { + private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems, currency: CryptoCurrency) { stateController.update( maybeTxHistoryItems.fold( ifLeft = { @@ -92,6 +94,7 @@ internal class TxHistorySubscriberV2( ifRight = { itemsFlow -> val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain() val itemConverter = TxHistoryItemStateConverter( + currency = currency, symbol = blockchain.currency, decimals = blockchain.decimals(), clickIntents = clickIntents, diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 07be659f64..cbabfbf53b 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.31-1314" +tangemBlockchainSdk = "releases-5.31.1-1316" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.31-569" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^