diff --git a/CHANGELOG.md b/CHANGELOG.md index 0255547d..324385b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - The SDK uses ZIP-317 fee system internally - `ZcashSdk.MINERS_FEE` has been deprecated, and will be removed in 2.1.0 +- `ZecSend` data class now provides `Proposal?` object initiated using `Synchronizer.proposeTransfer` ## [2.0.7] - 2024-03-08 diff --git a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/ui/screen/home/viewmodel/WalletViewModel.kt b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/ui/screen/home/viewmodel/WalletViewModel.kt index 69261dd0..7e53db95 100644 --- a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/ui/screen/home/viewmodel/WalletViewModel.kt +++ b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/ui/screen/home/viewmodel/WalletViewModel.kt @@ -231,7 +231,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application) runBlocking { val spendingKey = spendingKey.filterNotNull().first() kotlin.runCatching { - synchronizer.proposeSend(spendingKey, zecSend) + synchronizer.proposeSend(spendingKey.account, zecSend) }.onFailure { Twig.error(it) { "Failed to get transaction proposal" } }.getOrNull() diff --git a/sdk-incubator-lib/src/androidTest/kotlin/cash/z/ecc/android/sdk/fixture/ZecSendFixture.kt b/sdk-incubator-lib/src/androidTest/kotlin/cash/z/ecc/android/sdk/fixture/ZecSendFixture.kt index 6497a70c..413c1820 100644 --- a/sdk-incubator-lib/src/androidTest/kotlin/cash/z/ecc/android/sdk/fixture/ZecSendFixture.kt +++ b/sdk-incubator-lib/src/androidTest/kotlin/cash/z/ecc/android/sdk/fixture/ZecSendFixture.kt @@ -1,6 +1,7 @@ package cash.z.ecc.android.sdk.fixture import cash.z.ecc.android.sdk.model.Memo +import cash.z.ecc.android.sdk.model.Proposal import cash.z.ecc.android.sdk.model.WalletAddress import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.model.ZecSend @@ -12,9 +13,13 @@ object ZecSendFixture { val AMOUNT = Zatoshi(123) val MEMO = MemoFixture.new() + // Null until we figure out how to proper test this + val PROPOSAL = null + suspend fun new( address: String = ADDRESS, amount: Zatoshi = AMOUNT, - message: Memo = MEMO - ) = ZecSend(WalletAddress.Unified.new(address), amount, message) + message: Memo = MEMO, + proposal: Proposal? = PROPOSAL + ) = ZecSend(WalletAddress.Unified.new(address), amount, message, proposal) } diff --git a/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSend.kt b/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSend.kt index 919ae4c3..73464d6e 100644 --- a/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSend.kt +++ b/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSend.kt @@ -2,7 +2,12 @@ package cash.z.ecc.android.sdk.model import cash.z.ecc.android.sdk.Synchronizer -data class ZecSend(val destination: WalletAddress, val amount: Zatoshi, val memo: Memo) { +data class ZecSend( + val destination: WalletAddress, + val amount: Zatoshi, + val memo: Memo, + val proposal: Proposal? +) { companion object } @@ -19,11 +24,14 @@ suspend fun Synchronizer.send( spendingKey ) +/** + * This is just a syntactic sugar function for [Synchronizer.proposeTransfer] + */ suspend fun Synchronizer.proposeSend( - spendingKey: UnifiedSpendingKey, + account: Account, send: ZecSend ) = proposeTransfer( - spendingKey.account, + account, send.destination.address, send.amount, send.memo.value diff --git a/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSendExt.kt b/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSendExt.kt index e2765c89..c3a1aedd 100644 --- a/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSendExt.kt +++ b/sdk-incubator-lib/src/main/java/cash/z/ecc/android/sdk/model/ZecSendExt.kt @@ -28,7 +28,7 @@ object ZecSendExt { } return if (validationErrors.isEmpty()) { - ZecSendValidation.Valid(ZecSend(destination, amount!!, memo)) + ZecSendValidation.Valid(ZecSend(destination, amount!!, memo, null)) } else { ZecSendValidation.Invalid(validationErrors) } diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoderImpl.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoderImpl.kt index 33efc2b1..39e12bae 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoderImpl.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoderImpl.kt @@ -89,7 +89,7 @@ internal class TransactionEncoderImpl( }.onFailure { Twig.error(it) { "Caught exception while creating proposal." } }.onSuccess { result -> - Twig.debug { "result of proposeTransfer: $result" } + Twig.debug { "result of proposeTransfer: ${result.toPrettyString()}" } }.getOrThrow() } diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/Proposal.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/Proposal.kt index 8ae77d69..8cad767b 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/Proposal.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/Proposal.kt @@ -15,15 +15,22 @@ class Proposal( * @throws IllegalArgumentException if the proposal is invalid. */ @Throws(IllegalArgumentException::class) - fun fromUnsafe(proposal: ProposalUnsafe): Proposal { - val typed = Proposal(proposal) + fun fromUnsafe(proposal: ProposalUnsafe) = + Proposal(proposal).also { + it.check() + } - // Check for type errors eagerly, to ensure that the caller won't - // encounter these errors later. - typed.totalFeeRequired() + /** + * @throws IllegalArgumentException if the given [ByteArray] data could not be parsed and mapped to the new + * type-safe Proposal class. + */ + @Throws(IllegalArgumentException::class) + fun fromByteArray(array: ByteArray) = fromUnsafe(ProposalUnsafe.parse(array)) + } - return typed - } + // Check for type errors eagerly, to ensure that the caller won't encounter these errors later. + private fun check() { + totalFeeRequired() } /** @@ -33,6 +40,13 @@ class Proposal( return inner } + /** + * Serializes this proposal type-safe data to [ByteArray] for storing purposes. + */ + fun toByteArray(): ByteArray { + return inner.toByteArray() + } + /** * Returns the number of transactions that this proposal will create. *