diff --git a/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/mapper/rawtransaction/RawTransactionTypeDTODecider.kt b/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/mapper/rawtransaction/RawTransactionTypeDTODecider.kt index 9bad33079..8fe845a7f 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/mapper/rawtransaction/RawTransactionTypeDTODecider.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/mapper/rawtransaction/RawTransactionTypeDTODecider.kt @@ -24,6 +24,8 @@ class RawTransactionTypeDTODecider @Inject constructor() { RawTransactionTypePayload.ASSET_TRANSACTION -> RawTransactionTypeDTO.ASSET_TRANSACTION RawTransactionTypePayload.APP_TRANSACTION -> RawTransactionTypeDTO.APP_TRANSACTION RawTransactionTypePayload.ASSET_CONFIGURATION -> RawTransactionTypeDTO.ASSET_CONFIGURATION + RawTransactionTypePayload.KEYREG_TRANSACTION -> RawTransactionTypeDTO.KEYREG_TRANSACTION + RawTransactionTypePayload.HEARTBEAT_TRANSACTION -> RawTransactionTypeDTO.HEARTBEAT_TRANSACTION RawTransactionTypePayload.UNDEFINED -> RawTransactionTypeDTO.UNDEFINED } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/model/rawtransaction/RawTransactionTypePayload.kt b/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/model/rawtransaction/RawTransactionTypePayload.kt index ce48181d0..3fe14653f 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/model/rawtransaction/RawTransactionTypePayload.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/algosdk/data/model/rawtransaction/RawTransactionTypePayload.kt @@ -28,5 +28,11 @@ enum class RawTransactionTypePayload { @SerializedName("acfg") ASSET_CONFIGURATION, + @SerializedName("keyreg") + KEYREG_TRANSACTION, + + @SerializedName("hb") + HEARTBEAT_TRANSACTION, + UNDEFINED } diff --git a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/mapper/rawtransaction/RawTransactionTypeDTODecider.kt b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/mapper/rawtransaction/RawTransactionTypeDTODecider.kt index 7a8ca91d2..4a832af8c 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/mapper/rawtransaction/RawTransactionTypeDTODecider.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/mapper/rawtransaction/RawTransactionTypeDTODecider.kt @@ -24,6 +24,8 @@ class RawTransactionTypeDTODecider @Inject constructor() { RawTransactionTypeDTO.ASSET_TRANSACTION -> RawTransactionType.ASSET_TRANSACTION RawTransactionTypeDTO.APP_TRANSACTION -> RawTransactionType.APP_TRANSACTION RawTransactionTypeDTO.ASSET_CONFIGURATION -> RawTransactionType.ASSET_CONFIGURATION + RawTransactionTypeDTO.KEYREG_TRANSACTION -> RawTransactionType.KEYREG_TRANSACTION + RawTransactionTypeDTO.HEARTBEAT_TRANSACTION -> RawTransactionType.HEARTBEAT_TRANSACTION RawTransactionTypeDTO.UNDEFINED -> RawTransactionType.UNDEFINED } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/RawTransactionType.kt b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/RawTransactionType.kt index 60831df64..16b7cd0ab 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/RawTransactionType.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/RawTransactionType.kt @@ -17,5 +17,7 @@ enum class RawTransactionType { ASSET_TRANSACTION, APP_TRANSACTION, ASSET_CONFIGURATION, + KEYREG_TRANSACTION, + HEARTBEAT_TRANSACTION, UNDEFINED } diff --git a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/dto/RawTransactionTypeDTO.kt b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/dto/RawTransactionTypeDTO.kt index 37e09a4f1..feedb94c7 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/dto/RawTransactionTypeDTO.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/algosdk/domain/model/dto/RawTransactionTypeDTO.kt @@ -18,5 +18,7 @@ enum class RawTransactionTypeDTO { ASSET_TRANSACTION, APP_TRANSACTION, ASSET_CONFIGURATION, + KEYREG_TRANSACTION, + HEARTBEAT_TRANSACTION, UNDEFINED } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/mapper/TransactionTypeDTOMapper.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/mapper/TransactionTypeDTOMapper.kt index 0684f10cc..c3fbb7be9 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/mapper/TransactionTypeDTOMapper.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/mapper/TransactionTypeDTOMapper.kt @@ -25,7 +25,8 @@ class TransactionTypeDTOMapper @Inject constructor() { TransactionTypeResponse.ASSET_CONFIGURATION -> TransactionTypeDTO.ASSET_CONFIGURATION TransactionTypeResponse.APP_TRANSACTION -> TransactionTypeDTO.APP_TRANSACTION TransactionTypeResponse.UNDEFINED -> TransactionTypeDTO.UNDEFINED - TransactionTypeResponse.KEYREG -> TransactionTypeDTO.KEYREG_TRANSACTION + TransactionTypeResponse.KEYREG_TRANSACTION -> TransactionTypeDTO.KEYREG_TRANSACTION + TransactionTypeResponse.HEARTBEAT_TRANSACTION -> TransactionTypeDTO.HEARTBEAT_TRANSACTION } } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/model/TransactionTypeResponse.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/model/TransactionTypeResponse.kt index 19342cd6f..6aecab3da 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/model/TransactionTypeResponse.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/data/model/TransactionTypeResponse.kt @@ -29,7 +29,10 @@ enum class TransactionTypeResponse { ASSET_CONFIGURATION, @SerializedName("keyreg") - KEYREG, + KEYREG_TRANSACTION, + + @SerializedName("hb") + HEARTBEAT_TRANSACTION, UNDEFINED } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionDTO.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionDTO.kt index 2b2caf08e..d23f2da1e 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionDTO.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionDTO.kt @@ -34,3 +34,8 @@ data class TransactionDTO( val createdAssetIndex: Long?, val keyRegTransactionDTO: KeyRegTransactionDTO? ) + +fun TransactionDTO.getReceiverAddress(): String? { + return payment?.receiverAddress ?: assetTransfer?.receiverAddress + ?: assetFreezeTransaction?.receiverAddress.orEmpty() +} diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionTypeDTO.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionTypeDTO.kt index db5936d8f..6a11a4266 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionTypeDTO.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/common/domain/model/TransactionTypeDTO.kt @@ -18,5 +18,6 @@ enum class TransactionTypeDTO(val value: String?) { APP_TRANSACTION("appl"), ASSET_CONFIGURATION("acfg"), KEYREG_TRANSACTION("keyreg"), + HEARTBEAT_TRANSACTION("hb"), UNDEFINED(null) } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/mapper/BaseTransactionDetailMapper.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/mapper/BaseTransactionDetailMapper.kt index e1ca4198b..478326598 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/mapper/BaseTransactionDetailMapper.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/mapper/BaseTransactionDetailMapper.kt @@ -14,6 +14,7 @@ package com.algorand.android.modules.transaction.detail.domain.mapper import com.algorand.android.models.AssetInformation.Companion.ALGO_ID import com.algorand.android.modules.transaction.common.domain.model.TransactionDTO +import com.algorand.android.modules.transaction.common.domain.model.getReceiverAddress import com.algorand.android.modules.transaction.detail.domain.model.BaseTransactionDetail import com.algorand.android.modules.transaction.detail.domain.model.BaseTransactionDetail.BaseKeyRegTransaction.OfflineKeyRegTransaction import com.algorand.android.modules.transaction.detail.domain.model.BaseTransactionDetail.BaseKeyRegTransaction.OnlineKeyRegTransaction @@ -32,8 +33,7 @@ class BaseTransactionDetailMapper @Inject constructor() { id = id, signature = signature?.signatureKey, senderAccountAddress = senderAddress, - receiverAccountAddress = payment?.receiverAddress ?: assetTransfer?.receiverAddress - ?: assetFreezeTransaction?.receiverAddress.orEmpty(), + receiverAccountAddress = transactionDTO.getReceiverAddress(), closeToAccountAddress = payment?.closeToAddress ?: assetTransfer?.closeTo, roundTimeAsTimestamp = roundTimeAsTimestamp, confirmedRound = confirmedRound, @@ -53,8 +53,7 @@ class BaseTransactionDetailMapper @Inject constructor() { id = id, signature = signature?.signatureKey, senderAccountAddress = senderAddress, - receiverAccountAddress = payment?.receiverAddress ?: assetTransfer?.receiverAddress - ?: assetFreezeTransaction?.receiverAddress.orEmpty(), + receiverAccountAddress = transactionDTO.getReceiverAddress(), roundTimeAsTimestamp = roundTimeAsTimestamp, confirmedRound = confirmedRound, transactionAmount = payment?.amount ?: assetTransfer?.amount ?: BigInteger.ZERO, @@ -76,8 +75,7 @@ class BaseTransactionDetailMapper @Inject constructor() { id = id, signature = signature?.signatureKey, senderAccountAddress = senderAddress, - receiverAccountAddress = payment?.receiverAddress ?: assetTransfer?.receiverAddress - ?: assetFreezeTransaction?.receiverAddress.orEmpty(), + receiverAccountAddress = transactionDTO.getReceiverAddress(), roundTimeAsTimestamp = roundTimeAsTimestamp, confirmedRound = confirmedRound, fee = fee?.toBigInteger() ?: BigInteger.valueOf(MIN_FEE), @@ -101,8 +99,7 @@ class BaseTransactionDetailMapper @Inject constructor() { id = id, signature = signature?.signatureKey, senderAccountAddress = senderAddress, - receiverAccountAddress = payment?.receiverAddress ?: assetTransfer?.receiverAddress - ?: assetFreezeTransaction?.receiverAddress.orEmpty(), + receiverAccountAddress = transactionDTO.getReceiverAddress(), roundTimeAsTimestamp = roundTimeAsTimestamp, confirmedRound = confirmedRound, fee = fee?.toBigInteger() ?: BigInteger.valueOf(MIN_FEE), @@ -130,14 +127,28 @@ class BaseTransactionDetailMapper @Inject constructor() { } } + fun mapToHeartbeatTransactionDetail(transactionDTO: TransactionDTO): BaseTransactionDetail.HeartbeatTransaction { + return with(transactionDTO) { + BaseTransactionDetail.HeartbeatTransaction( + id = id, + signature = signature?.signatureKey, + senderAccountAddress = senderAddress, + receiverAccountAddress = null, + roundTimeAsTimestamp = roundTimeAsTimestamp, + confirmedRound = confirmedRound, + fee = fee?.toBigInteger() ?: BigInteger.valueOf(MIN_FEE), + noteInBase64 = noteInBase64 + ) + } + } + fun mapToUndefinedTransactionDetail(transactionDTO: TransactionDTO): BaseTransactionDetail.UndefinedTransaction { return with(transactionDTO) { BaseTransactionDetail.UndefinedTransaction( id = id, signature = signature?.signatureKey, senderAccountAddress = senderAddress, - receiverAccountAddress = payment?.receiverAddress ?: assetTransfer?.receiverAddress - ?: assetFreezeTransaction?.receiverAddress.orEmpty(), + receiverAccountAddress = transactionDTO.getReceiverAddress(), roundTimeAsTimestamp = roundTimeAsTimestamp, confirmedRound = confirmedRound, fee = fee?.toBigInteger() ?: BigInteger.valueOf(MIN_FEE), diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/model/BaseTransactionDetail.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/model/BaseTransactionDetail.kt index 5f53442e9..2c76a9af5 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/model/BaseTransactionDetail.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/model/BaseTransactionDetail.kt @@ -188,4 +188,23 @@ sealed class BaseTransactionDetail : Parcelable { get() = R.string.transaction_detail } } + + @Parcelize + data class HeartbeatTransaction( + override val id: String? = null, + override val signature: String? = null, + override val senderAccountAddress: String? = null, + override val receiverAccountAddress: String? = null, + override val roundTimeAsTimestamp: Long? = null, + override val confirmedRound: Long?, + override val fee: BigInteger, + override val noteInBase64: String? = null, + override val closeToAccountAddress: String? = null, + override val transactionCloseAmount: BigInteger? = null, + override val transactionAmount: BigInteger? = null + ) : BaseTransactionDetail() { + + override val toolbarTitleResId: Int + get() = R.string.transaction_detail + } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/BaseTransactionDetailPreviewUseCase.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/BaseTransactionDetailPreviewUseCase.kt index 02feb45af..5f8cde42b 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/BaseTransactionDetailPreviewUseCase.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/BaseTransactionDetailPreviewUseCase.kt @@ -139,7 +139,8 @@ open class BaseTransactionDetailPreviewUseCase constructor( is BaseTransactionDetail.PaymentTransaction -> ALGO_ID is BaseTransactionDetail.ApplicationCallTransaction, is BaseTransactionDetail.UndefinedTransaction, - is BaseTransactionDetail.BaseKeyRegTransaction -> null + is BaseTransactionDetail.BaseKeyRegTransaction, + is BaseTransactionDetail.HeartbeatTransaction -> null } ?: ALGO_ID } @@ -166,7 +167,8 @@ open class BaseTransactionDetailPreviewUseCase constructor( is BaseTransactionDetail.ApplicationCallTransaction, is BaseTransactionDetail.AssetConfigurationTransaction, is BaseTransactionDetail.UndefinedTransaction, - is BaseTransactionDetail.BaseKeyRegTransaction -> null + is BaseTransactionDetail.BaseKeyRegTransaction, + is BaseTransactionDetail.HeartbeatTransaction -> null } ?: BigInteger.ZERO } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/GetTransactionDetailUseCase.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/GetTransactionDetailUseCase.kt index a7bfb35e2..3709a03c5 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/GetTransactionDetailUseCase.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/GetTransactionDetailUseCase.kt @@ -18,6 +18,7 @@ import com.algorand.android.modules.transaction.common.domain.model.TransactionT import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.ASSET_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.KEYREG_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.PAY_TRANSACTION +import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.HEARTBEAT_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.UNDEFINED import com.algorand.android.modules.transaction.detail.domain.mapper.BaseTransactionDetailMapper import com.algorand.android.modules.transaction.detail.domain.model.BaseTransactionDetail @@ -63,6 +64,7 @@ class GetTransactionDetailUseCase @Inject constructor( ASSET_CONFIGURATION -> baseTransactionDetailMapper.mapToAssetConfigurationTransactionDetail(this) UNDEFINED -> baseTransactionDetailMapper.mapToUndefinedTransactionDetail(this) KEYREG_TRANSACTION -> baseTransactionDetailMapper.mapToKeyRegTransactionDetail(this) + HEARTBEAT_TRANSACTION -> baseTransactionDetailMapper.mapToHeartbeatTransactionDetail(this) null -> baseTransactionDetailMapper.mapToUndefinedTransactionDetail(this) } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/InnerTransactionDetailPreviewUseCase.kt b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/InnerTransactionDetailPreviewUseCase.kt index da4fd5cee..7fdcd5770 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/InnerTransactionDetailPreviewUseCase.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transaction/detail/domain/usecase/InnerTransactionDetailPreviewUseCase.kt @@ -73,6 +73,7 @@ class InnerTransactionDetailPreviewUseCase @Inject constructor( is BaseTransactionDetail.AssetTransferTransaction, is BaseTransactionDetail.PaymentTransaction, is BaseTransactionDetail.UndefinedTransaction, + is BaseTransactionDetail.HeartbeatTransaction, is BaseTransactionDetail.BaseKeyRegTransaction -> { createStandardTransactionItem(transaction = baseTransactionDetail, publicKey = publicKey) } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/mapper/BaseTransactionMapper.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/mapper/BaseTransactionMapper.kt index 3b7d5f027..470ece445 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/mapper/BaseTransactionMapper.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/mapper/BaseTransactionMapper.kt @@ -13,6 +13,7 @@ package com.algorand.android.modules.transactionhistory.domain.mapper import com.algorand.android.modules.transaction.common.domain.model.TransactionDTO +import com.algorand.android.modules.transaction.common.domain.model.getReceiverAddress import com.algorand.android.modules.transactionhistory.domain.model.BaseTransaction import com.algorand.android.utils.getAllNestedTransactions import com.algorand.android.utils.getZonedDateTimeFromTimeStamp @@ -21,9 +22,9 @@ import javax.inject.Inject class BaseTransactionMapper @Inject constructor() { fun mapToPayTransactionSend( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.Pay.Send { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.Pay.Send( id = id, signature = signature?.signatureKey, @@ -37,9 +38,9 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToPayTransactionReceive( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.Pay.Receive { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.Pay.Receive( id = id, signature = signature?.signatureKey, @@ -53,9 +54,9 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToPayTransactionSelf( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.Pay.Self { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.Pay.Self( id = id, signature = signature?.signatureKey, @@ -69,144 +70,137 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToAssetTransactionSend( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.AssetTransfer.BaseSend.Send? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseSend.Send( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null ) } } fun mapToAssetTransactionReceive( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.AssetTransfer.BaseReceive.Receive? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseReceive.Receive( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null ) } } fun mapToAssetTransactionReceiveOptOut( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.AssetTransfer.BaseReceive.ReceiveOptOut? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseReceive.ReceiveOptOut( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null ) } } fun mapToAssetTransactionOptOut( - transaction: TransactionDTO, + transactionDTO: TransactionDTO, closeToAddress: String, ): BaseTransaction.Transaction.AssetTransfer.OptOut? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.OptOut( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId, + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null, closeToAddress = closeToAddress ) } } fun mapToAssetTransactionSendOptOut( - transaction: TransactionDTO, + transactionDTO: TransactionDTO, closeToAddress: String, ): BaseTransaction.Transaction.AssetTransfer.BaseSend.SendOptOut? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseSend.SendOptOut( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId, + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null, closeToAddress = closeToAddress ) } } fun mapToAssetTransactionSelf( - transaction: TransactionDTO, + transactionDTO: TransactionDTO, ): BaseTransaction.Transaction.AssetTransfer.BaseSelf.Self? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseSelf.Self( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = transactionDTO.getReceiverAddress(), zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null ) } } fun mapToAssetTransactionSelfOptIn( - transaction: TransactionDTO, + transactionDTO: TransactionDTO, ): BaseTransaction.Transaction.AssetTransfer.BaseSelf.SelfOptIn? { - return with(transaction) { - val assetId = assetTransfer?.assetId ?: return null + return with(transactionDTO) { BaseTransaction.Transaction.AssetTransfer.BaseSelf.SelfOptIn( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = assetTransfer.receiverAddress, + receiverAddress = assetTransfer?.receiverAddress, zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, - amount = assetTransfer.amount ?: BigInteger.ZERO, - assetId = assetId + amount = assetTransfer?.amount ?: BigInteger.ZERO, + assetId = assetTransfer?.assetId ?: return null ) } } fun mapToAssetConfiguration( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.AssetConfiguration { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.AssetConfiguration( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = null, // Asset Configuration Transaction does not contain receiver address + receiverAddress = transactionDTO.getReceiverAddress(), zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, assetId = createdAssetIndex ?: assetConfiguration?.assetId @@ -215,9 +209,9 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToOnlineKeyReg( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.KeyReg.Online { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.KeyReg.Online( id = id, signature = signature?.signatureKey, @@ -236,9 +230,9 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToOfflineKeyReg( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.KeyReg.Offline { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.KeyReg.Offline( id = id, signature = signature?.signatureKey, @@ -252,14 +246,14 @@ class BaseTransactionMapper @Inject constructor() { } fun mapToApplicationCall( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.ApplicationCall { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.ApplicationCall( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = null, // Application Call Transaction does not contain receiver address + receiverAddress = transactionDTO.getReceiverAddress(), zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false, applicationId = applicationCall?.applicationId, @@ -269,15 +263,30 @@ class BaseTransactionMapper @Inject constructor() { } } + fun mapToHeartbeat( + transactionDTO: TransactionDTO + ): BaseTransaction.Transaction.Heartbeat { + return with(transactionDTO) { + BaseTransaction.Transaction.Heartbeat( + id = id, + signature = signature?.signatureKey, + senderAddress = senderAddress.orEmpty(), + receiverAddress = null, + zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), + isPending = false + ) + } + } + fun mapToUndefined( - transaction: TransactionDTO + transactionDTO: TransactionDTO ): BaseTransaction.Transaction.Undefined { - return with(transaction) { + return with(transactionDTO) { BaseTransaction.Transaction.Undefined( id = id, signature = signature?.signatureKey, senderAddress = senderAddress.orEmpty(), - receiverAddress = null, // Undefined Transaction does not contain receiver address + receiverAddress = transactionDTO.getReceiverAddress(), zonedDateTime = roundTimeAsTimestamp?.getZonedDateTimeFromTimeStamp(), isPending = false ) diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/model/BaseTransaction.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/model/BaseTransaction.kt index 8eca041f7..7cf27bef3 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/model/BaseTransaction.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/model/BaseTransaction.kt @@ -196,6 +196,15 @@ sealed class BaseTransaction { ) : KeyReg() } + data class Heartbeat( + override val id: String?, + override val signature: String?, + override val senderAddress: String?, + override val receiverAddress: String?, + override val zonedDateTime: ZonedDateTime?, + override val isPending: Boolean + ) : Transaction() + data class Undefined( override val id: String? = null, override val signature: String? = null, diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/usecase/TransactionHistoryUseCase.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/usecase/TransactionHistoryUseCase.kt index e8c25c431..3aecd8a2c 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/usecase/TransactionHistoryUseCase.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/domain/usecase/TransactionHistoryUseCase.kt @@ -24,6 +24,7 @@ import com.algorand.android.modules.transaction.common.domain.model.TransactionD import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.APP_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.ASSET_CONFIGURATION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.ASSET_TRANSACTION +import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.HEARTBEAT_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.KEYREG_TRANSACTION import com.algorand.android.modules.transaction.common.domain.model.TransactionTypeDTO.PAY_TRANSACTION import com.algorand.android.modules.transactionhistory.domain.mapper.BaseTransactionMapper @@ -109,6 +110,7 @@ class TransactionHistoryUseCase @Inject constructor( ASSET_CONFIGURATION -> baseTransactionMapper.mapToAssetConfiguration(txn) APP_TRANSACTION -> baseTransactionMapper.mapToApplicationCall(txn) KEYREG_TRANSACTION -> createKeyRegTransaction(txn) + HEARTBEAT_TRANSACTION -> createHeartbeatTransaction(txn) else -> baseTransactionMapper.mapToUndefined(txn) } } @@ -211,13 +213,13 @@ class TransactionHistoryUseCase @Inject constructor( val senderAddress = transactionDTO.senderAddress return when { isSelfTransaction(publicKey, senderAddress, receiverAddress) -> { - baseTransactionMapper.mapToPayTransactionSelf(transaction = transactionDTO) + baseTransactionMapper.mapToPayTransactionSelf(transactionDTO = transactionDTO) } isReceiveTransaction(publicKey, closeToAddress, receiverAddress) -> { - baseTransactionMapper.mapToPayTransactionReceive(transaction = transactionDTO) + baseTransactionMapper.mapToPayTransactionReceive(transactionDTO = transactionDTO) } else -> { - baseTransactionMapper.mapToPayTransactionSend(transaction = transactionDTO) + baseTransactionMapper.mapToPayTransactionSend(transactionDTO = transactionDTO) } } } @@ -233,22 +235,22 @@ class TransactionHistoryUseCase @Inject constructor( return with(baseTransactionMapper) { when { !closeToAddress.isNullOrBlank() && closeToAddress == publicKey -> { - mapToAssetTransactionReceiveOptOut(transaction = transactionDTO) + mapToAssetTransactionReceiveOptOut(transactionDTO = transactionDTO) } !closeToAddress.isNullOrBlank() && amount.isGreaterThan(BigInteger.ZERO) -> { - mapToAssetTransactionSendOptOut(closeToAddress = closeToAddress, transaction = transactionDTO) + mapToAssetTransactionSendOptOut(closeToAddress = closeToAddress, transactionDTO = transactionDTO) } !closeToAddress.isNullOrBlank() -> { - mapToAssetTransactionOptOut(closeToAddress = closeToAddress, transaction = transactionDTO) + mapToAssetTransactionOptOut(closeToAddress = closeToAddress, transactionDTO = transactionDTO) } isSelfOptInTransaction(publicKey, senderAddress, receiverAddress, amount) -> { - mapToAssetTransactionSelfOptIn(transaction = transactionDTO) + mapToAssetTransactionSelfOptIn(transactionDTO = transactionDTO) } isSelfTransaction(publicKey, senderAddress, receiverAddress) -> { - mapToAssetTransactionSelf(transaction = transactionDTO) + mapToAssetTransactionSelf(transactionDTO = transactionDTO) } isReceiveTransaction(publicKey, closeToAddress, receiverAddress) -> { - mapToAssetTransactionReceive(transaction = transactionDTO) + mapToAssetTransactionReceive(transactionDTO = transactionDTO) } else -> mapToAssetTransactionSend(transactionDTO) } @@ -262,4 +264,8 @@ class TransactionHistoryUseCase @Inject constructor( baseTransactionMapper.mapToOfflineKeyReg(txn) } } + + private fun createHeartbeatTransaction(txn: TransactionDTO): BaseTransaction.Transaction.Heartbeat { + return baseTransactionMapper.mapToHeartbeat(txn) + } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/mapper/TransactionItemMapper.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/mapper/TransactionItemMapper.kt index f9e8aa3e5..dbe114ada 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/mapper/TransactionItemMapper.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/mapper/TransactionItemMapper.kt @@ -261,4 +261,16 @@ class TransactionItemMapper @Inject constructor() { isPending = transaction.isPending ) } + + fun mapToHeartbeatTransactionItem( + transaction: BaseTransaction.Transaction.Heartbeat + ): BaseTransactionItem.TransactionItem.HeartbeatItem { + return with(transaction) { + BaseTransactionItem.TransactionItem.HeartbeatItem( + id = id, + signature = signature, + isPending = isPending + ) + } + } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/model/BaseTransactionItem.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/model/BaseTransactionItem.kt index 64437d5c2..60ea3e92d 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/model/BaseTransactionItem.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/model/BaseTransactionItem.kt @@ -304,6 +304,24 @@ sealed class BaseTransactionItem : RecyclerListItem, Parcelable { } } + @Parcelize + data class HeartbeatItem( + override val id: String? = null, + override val signature: String? = null, + override val nameRes: Int? = R.string.heartbeat, + override val description: String? = null, + override val formattedAmount: String? = null, + override val isAmountVisible: Boolean = false, + override val isPending: Boolean = false, + override val amountColorRes: Int? = null + ) : TransactionItem() { + + override fun isSameTransaction(other: RecyclerListItem): Boolean { + val transaction = other as? HeartbeatItem ?: return false + return signature != null && signature == transaction.signature + } + } + @Parcelize data class UndefinedItem( override val id: String? = null, diff --git a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/usecase/BaseTransactionPreviewUseCase.kt b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/usecase/BaseTransactionPreviewUseCase.kt index 3818359cc..885d02560 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/usecase/BaseTransactionPreviewUseCase.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/transactionhistory/ui/usecase/BaseTransactionPreviewUseCase.kt @@ -62,6 +62,7 @@ open class BaseTransactionPreviewUseCase constructor( is BaseTransaction.TransactionDateTitle -> transactionItemMapper.mapToTransactionDateTitle(txn) is BaseTransaction.PendingTransactionTitle -> transactionItemMapper.mapToPendingTransactionTitle(txn) is BaseTransaction.Transaction.KeyReg -> transactionItemMapper.mapToKeyRegTransactionItem(txn) + is BaseTransaction.Transaction.Heartbeat -> transactionItemMapper.mapToHeartbeatTransactionItem(txn) } } diff --git a/app/src/main/kotlin/com/algorand/android/modules/walletconnect/ui/mapper/WalletConnectTransactionMapper.kt b/app/src/main/kotlin/com/algorand/android/modules/walletconnect/ui/mapper/WalletConnectTransactionMapper.kt index 1c0bfb412..176d26d8c 100644 --- a/app/src/main/kotlin/com/algorand/android/modules/walletconnect/ui/mapper/WalletConnectTransactionMapper.kt +++ b/app/src/main/kotlin/com/algorand/android/modules/walletconnect/ui/mapper/WalletConnectTransactionMapper.kt @@ -25,7 +25,7 @@ import com.algorand.android.models.WalletConnectSession import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.APP_TRANSACTION import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.ASSET_CONFIGURATION import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.ASSET_TRANSACTION -import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.KEYREG +import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.KEYREG_TRANSACTION import com.algorand.android.modules.transaction.common.data.model.TransactionTypeResponse.PAY_TRANSACTION import com.algorand.android.modules.walletconnect.domain.model.WalletConnect import com.algorand.android.utils.walletconnect.getTransactionRequest @@ -95,7 +95,7 @@ class WalletConnectTransactionMapper @Inject constructor( assetConfigurationTransactionMapper.createTransaction(walletConnectPeerMeta, transactionRequest, rawTxn) } - KEYREG -> { + KEYREG_TRANSACTION -> { keyRegTransactionMapper.createTransaction(walletConnectPeerMeta, transactionRequest, rawTxn) } diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 837e68b06..04a20349a 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -120,4 +120,6 @@ WCV1 datePlaceholder, hourReplacement KeyReg + + Heartbeat diff --git a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImpl.kt b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImpl.kt index 07c05f714..d268913ee 100644 --- a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImpl.kt +++ b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImpl.kt @@ -24,6 +24,8 @@ internal class RawTransactionTypeMapperImpl @Inject constructor() : RawTransacti RawTransactionTypePayload.ASSET_TRANSACTION -> RawTransactionType.ASSET_TRANSACTION RawTransactionTypePayload.APP_TRANSACTION -> RawTransactionType.APP_TRANSACTION RawTransactionTypePayload.ASSET_CONFIGURATION -> RawTransactionType.ASSET_CONFIGURATION + RawTransactionTypePayload.KEYREG_TRANSACTION -> RawTransactionType.KEYREG_TRANSACTION + RawTransactionTypePayload.HEARTBEAT_TRANSACTION -> RawTransactionType.HEARTBEAT_TRANSACTION RawTransactionTypePayload.UNDEFINED -> RawTransactionType.UNDEFINED } } diff --git a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/RawTransactionType.kt b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/RawTransactionType.kt index 444079d53..915fe1ae5 100644 --- a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/RawTransactionType.kt +++ b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/RawTransactionType.kt @@ -17,5 +17,7 @@ enum class RawTransactionType { ASSET_TRANSACTION, APP_TRANSACTION, ASSET_CONFIGURATION, + KEYREG_TRANSACTION, + HEARTBEAT_TRANSACTION, UNDEFINED } diff --git a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/payload/RawTransactionTypePayload.kt b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/payload/RawTransactionTypePayload.kt index 530889e97..2f8e1271a 100644 --- a/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/payload/RawTransactionTypePayload.kt +++ b/common-sdk/src/main/kotlin/com/algorand/wallet/algosdk/transaction/model/payload/RawTransactionTypePayload.kt @@ -28,5 +28,11 @@ internal enum class RawTransactionTypePayload { @SerializedName("acfg") ASSET_CONFIGURATION, + @SerializedName("keyreg") + KEYREG_TRANSACTION, + + @SerializedName("hb") + HEARTBEAT_TRANSACTION, + UNDEFINED } diff --git a/common-sdk/src/test/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImplTest.kt b/common-sdk/src/test/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImplTest.kt index f5bf00083..943e2be6b 100644 --- a/common-sdk/src/test/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImplTest.kt +++ b/common-sdk/src/test/kotlin/com/algorand/wallet/algosdk/transaction/mapper/RawTransactionTypeMapperImplTest.kt @@ -15,12 +15,16 @@ class RawTransactionTypeMapperImplTest { val assetTxnResult = sut(RawTransactionTypePayload.ASSET_TRANSACTION) val appTxnResult = sut(RawTransactionTypePayload.APP_TRANSACTION) val assetConfigResult = sut(RawTransactionTypePayload.ASSET_CONFIGURATION) + val keyRegTxnResult = sut(RawTransactionTypePayload.KEYREG_TRANSACTION) + val heartbeatTxnResult = sut(RawTransactionTypePayload.HEARTBEAT_TRANSACTION) val undefinedResult = sut(RawTransactionTypePayload.UNDEFINED) assertEquals(RawTransactionType.PAY_TRANSACTION, payTxnResult) assertEquals(RawTransactionType.ASSET_TRANSACTION, assetTxnResult) assertEquals(RawTransactionType.APP_TRANSACTION, appTxnResult) assertEquals(RawTransactionType.ASSET_CONFIGURATION, assetConfigResult) + assertEquals(RawTransactionType.KEYREG_TRANSACTION, keyRegTxnResult) + assertEquals(RawTransactionType.HEARTBEAT_TRANSACTION, heartbeatTxnResult) assertEquals(RawTransactionType.UNDEFINED, undefinedResult) } }