From a1cc8f0b6936513b79e43e648e2b78464ce6bba9 Mon Sep 17 00:00:00 2001 From: Carter Jernigan Date: Thu, 7 Jul 2022 08:52:07 -0400 Subject: [PATCH] [#477] Fixes for Zatoshi object --- MIGRATIONS.md | 2 ++ .../android/sdk/darkside/test/TestWallet.kt | 2 +- .../demos/getbalance/GetBalanceFragment.kt | 2 +- .../sdk/demoapp/demos/send/SendFragment.kt | 2 +- .../cash/z/ecc/android/sdk/util/TestWallet.kt | 2 +- .../cash/z/ecc/android/sdk/SdkSynchronizer.kt | 2 +- .../cash/z/ecc/android/sdk/Synchronizer.kt | 2 +- .../sdk/block/CompactBlockProcessor.kt | 2 +- .../ecc/android/sdk/db/entity/Transactions.kt | 4 +++ .../PersistentTransactionManager.kt | 2 +- .../transaction/TransactionEncoder.kt | 3 +- .../transaction/WalletTransactionEncoder.kt | 17 ++++++----- .../cash/z/ecc/android/sdk/jni/RustBackend.kt | 2 +- .../ecc/android/sdk/jni/RustBackendWelding.kt | 2 +- .../z/ecc/android/sdk/model/WalletBalance.kt | 28 ++++++++++++++++++ .../z/ecc/android/sdk/type/WalletTypes.kt | 29 ------------------- .../z/ecc/android/sdk/ext/ConversionsTest.kt | 9 +++--- 17 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/WalletBalance.kt diff --git a/MIGRATIONS.md b/MIGRATIONS.md index d5ce8119..b898c5c1 100644 --- a/MIGRATIONS.md +++ b/MIGRATIONS.md @@ -7,6 +7,8 @@ Various APIs used `Long` value to represent Zatoshi currency amounts. Those API `WalletBalance` no longer has uninitialized default values. This means that `Synchronizer` fields that expose a WalletBalance now use `null` to signal an uninitialized value. Specifically this means `Synchronizer.orchardBalances`, `Synchronzier.saplingBalances`, and `Synchronizer.transparentBalances` have nullable values now. +`WalletBalance` has been moved from the package `cash.z.ecc.android.sdk.type` to `cash.z.ecc.android.sdk.model` + `ZcashSdk.ZATOSHI_PER_ZEC` has been moved to `Zatoshi.ZATOSHI_PER_ZEC`. `ZcashSdk.MINERS_FEE_ZATOSHI` has been renamed to `ZcashSdk.MINERS_FEE` and the type has changed from `Long` to `Zatoshi`. diff --git a/darkside-test-lib/src/androidTest/java/cash/z/ecc/android/sdk/darkside/test/TestWallet.kt b/darkside-test-lib/src/androidTest/java/cash/z/ecc/android/sdk/darkside/test/TestWallet.kt index 3490a5ac..fd7ae582 100644 --- a/darkside-test-lib/src/androidTest/java/cash/z/ecc/android/sdk/darkside/test/TestWallet.kt +++ b/darkside-test-lib/src/androidTest/java/cash/z/ecc/android/sdk/darkside/test/TestWallet.kt @@ -10,9 +10,9 @@ import cash.z.ecc.android.sdk.db.entity.isPending import cash.z.ecc.android.sdk.internal.Twig import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService import cash.z.ecc.android.sdk.internal.twig +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.tool.DerivationTool -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob diff --git a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getbalance/GetBalanceFragment.kt b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getbalance/GetBalanceFragment.kt index cb41bf8f..2f8f02ef 100644 --- a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getbalance/GetBalanceFragment.kt +++ b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getbalance/GetBalanceFragment.kt @@ -14,8 +14,8 @@ import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext import cash.z.ecc.android.sdk.demoapp.util.fromResources import cash.z.ecc.android.sdk.ext.collectWith import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.tool.DerivationTool -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.runBlocking diff --git a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/send/SendFragment.kt b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/send/SendFragment.kt index 4a005c47..d10f1618 100644 --- a/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/send/SendFragment.kt +++ b/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/send/SendFragment.kt @@ -29,8 +29,8 @@ import cash.z.ecc.android.sdk.ext.convertZecToZatoshi import cash.z.ecc.android.sdk.ext.toZecString import cash.z.ecc.android.sdk.internal.Twig import cash.z.ecc.android.sdk.internal.twig +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.tool.DerivationTool -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import kotlinx.coroutines.runBlocking diff --git a/sdk-lib/src/androidTest/java/cash/z/ecc/android/sdk/util/TestWallet.kt b/sdk-lib/src/androidTest/java/cash/z/ecc/android/sdk/util/TestWallet.kt index 4efe0cbd..a572a399 100644 --- a/sdk-lib/src/androidTest/java/cash/z/ecc/android/sdk/util/TestWallet.kt +++ b/sdk-lib/src/androidTest/java/cash/z/ecc/android/sdk/util/TestWallet.kt @@ -10,9 +10,9 @@ import cash.z.ecc.android.sdk.db.entity.isPending import cash.z.ecc.android.sdk.internal.Twig import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService import cash.z.ecc.android.sdk.internal.twig +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.tool.DerivationTool -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt index 97ab7811..f6ad5db7 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt @@ -46,13 +46,13 @@ import cash.z.ecc.android.sdk.internal.transaction.TransactionRepository import cash.z.ecc.android.sdk.internal.transaction.WalletTransactionEncoder import cash.z.ecc.android.sdk.internal.twig import cash.z.ecc.android.sdk.internal.twigTask +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.tool.DerivationTool import cash.z.ecc.android.sdk.type.AddressType import cash.z.ecc.android.sdk.type.AddressType.Shielded import cash.z.ecc.android.sdk.type.AddressType.Transparent import cash.z.ecc.android.sdk.type.ConsensusMatchType -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import cash.z.wallet.sdk.rpc.Service import io.grpc.ManagedChannel diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt index 6d4f17c7..b0153d36 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt @@ -4,10 +4,10 @@ import cash.z.ecc.android.sdk.block.CompactBlockProcessor import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction import cash.z.ecc.android.sdk.db.entity.PendingTransaction import cash.z.ecc.android.sdk.ext.ZcashSdk +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.type.AddressType import cash.z.ecc.android.sdk.type.ConsensusMatchType -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import cash.z.wallet.sdk.rpc.Service import kotlinx.coroutines.CoroutineScope diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockProcessor.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockProcessor.kt index 8e7362fd..cb5ab0dd 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockProcessor.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockProcessor.kt @@ -39,7 +39,7 @@ import cash.z.ecc.android.sdk.internal.twig import cash.z.ecc.android.sdk.internal.twigTask import cash.z.ecc.android.sdk.jni.RustBackend import cash.z.ecc.android.sdk.jni.RustBackendWelding -import cash.z.ecc.android.sdk.type.WalletBalance +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.wallet.sdk.rpc.Service import io.grpc.StatusRuntimeException import kotlinx.coroutines.Dispatchers diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/db/entity/Transactions.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/db/entity/Transactions.kt index 77278b99..95542a16 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/db/entity/Transactions.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/db/entity/Transactions.kt @@ -96,6 +96,10 @@ data class PendingTransactionEntity( @ColumnInfo(typeAffinity = ColumnInfo.BLOB) override val rawTransactionId: ByteArray? = byteArrayOf() ) : PendingTransaction { + + val valueZatoshi: Zatoshi + get() = Zatoshi(value) + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is PendingTransactionEntity) return false diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/PersistentTransactionManager.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/PersistentTransactionManager.kt index cdc1c90a..2e9298e7 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/PersistentTransactionManager.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/PersistentTransactionManager.kt @@ -115,7 +115,7 @@ class PersistentTransactionManager( twig("beginning to encode transaction with : $encoder") val encodedTx = encoder.createTransaction( spendingKey, - tx.value, + tx.valueZatoshi, tx.toAddress, tx.memo, tx.accountIndex diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoder.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoder.kt index e7c4d531..9b9157ae 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoder.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/TransactionEncoder.kt @@ -1,6 +1,7 @@ package cash.z.ecc.android.sdk.internal.transaction import cash.z.ecc.android.sdk.db.entity.EncodedTransaction +import cash.z.ecc.android.sdk.model.Zatoshi interface TransactionEncoder { /** @@ -18,7 +19,7 @@ interface TransactionEncoder { */ suspend fun createTransaction( spendingKey: String, - zatoshi: Long, + amount: Zatoshi, toAddress: String, memo: ByteArray? = byteArrayOf(), fromAccountIndex: Int = 0 diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/WalletTransactionEncoder.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/WalletTransactionEncoder.kt index 54edaad5..db8d9959 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/WalletTransactionEncoder.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/transaction/WalletTransactionEncoder.kt @@ -8,6 +8,7 @@ import cash.z.ecc.android.sdk.internal.twig import cash.z.ecc.android.sdk.internal.twigTask import cash.z.ecc.android.sdk.jni.RustBackend import cash.z.ecc.android.sdk.jni.RustBackendWelding +import cash.z.ecc.android.sdk.model.Zatoshi /** * Class responsible for encoding a transaction in a consistent way. This bridges the gap by @@ -18,7 +19,7 @@ import cash.z.ecc.android.sdk.jni.RustBackendWelding * @property repository the repository that stores information about the transactions being created * such as the raw bytes and raw txId. */ -class WalletTransactionEncoder( +internal class WalletTransactionEncoder( private val rustBackend: RustBackendWelding, private val repository: TransactionRepository ) : TransactionEncoder { @@ -29,7 +30,7 @@ class WalletTransactionEncoder( * exception ourselves (rather than using double-bangs for things). * * @param spendingKey the key associated with the notes that will be spent. - * @param zatoshi the amount of zatoshi to send. + * @param amount the amount of zatoshi to send. * @param toAddress the recipient's address. * @param memo the optional memo to include as part of the transaction. * @param fromAccountIndex the optional account id to use. By default, the 1st account is used. @@ -38,12 +39,12 @@ class WalletTransactionEncoder( */ override suspend fun createTransaction( spendingKey: String, - zatoshi: Long, + amount: Zatoshi, toAddress: String, memo: ByteArray?, fromAccountIndex: Int ): EncodedTransaction { - val transactionId = createSpend(spendingKey, zatoshi, toAddress, memo) + val transactionId = createSpend(spendingKey, amount, toAddress, memo) return repository.findEncodedTransactionById(transactionId) ?: throw TransactionEncoderException.TransactionNotFoundException(transactionId) } @@ -93,7 +94,7 @@ class WalletTransactionEncoder( * the result in the database. On average, this call takes over 10 seconds. * * @param spendingKey the key associated with the notes that will be spent. - * @param zatoshi the amount of zatoshi to send. + * @param amount the amount of zatoshi to send. * @param toAddress the recipient's address. * @param memo the optional memo to include as part of the transaction. * @param fromAccountIndex the optional account id to use. By default, the 1st account is used. @@ -103,13 +104,13 @@ class WalletTransactionEncoder( */ private suspend fun createSpend( spendingKey: String, - zatoshi: Long, + amount: Zatoshi, toAddress: String, memo: ByteArray? = byteArrayOf(), fromAccountIndex: Int = 0 ): Long { return twigTask( - "creating transaction to spend $zatoshi zatoshi to" + + "creating transaction to spend $amount zatoshi to" + " ${toAddress.masked()} with memo $memo" ) { try { @@ -121,7 +122,7 @@ class WalletTransactionEncoder( fromAccountIndex, spendingKey, toAddress, - zatoshi, + amount.value, memo ) } catch (t: Throwable) { diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt index 6c5500d4..1ace162d 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt @@ -6,10 +6,10 @@ import cash.z.ecc.android.sdk.ext.ZcashSdk.SPEND_PARAM_FILE_NAME import cash.z.ecc.android.sdk.internal.SdkDispatchers import cash.z.ecc.android.sdk.internal.ext.deleteSuspend import cash.z.ecc.android.sdk.internal.twig +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.tool.DerivationTool import cash.z.ecc.android.sdk.type.UnifiedViewingKey -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork import kotlinx.coroutines.withContext import java.io.File diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackendWelding.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackendWelding.kt index 72b896f5..6bb4b405 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackendWelding.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackendWelding.kt @@ -1,8 +1,8 @@ package cash.z.ecc.android.sdk.jni +import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.type.UnifiedViewingKey -import cash.z.ecc.android.sdk.type.WalletBalance import cash.z.ecc.android.sdk.type.ZcashNetwork /** diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/WalletBalance.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/WalletBalance.kt new file mode 100644 index 00000000..a2c4e16d --- /dev/null +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/WalletBalance.kt @@ -0,0 +1,28 @@ +package cash.z.ecc.android.sdk.model + +/** + * Data structure to hold the total and available balance of the wallet. This is what is + * received on the balance channel. + * + * @param total the total balance, ignoring funds that cannot be used. + * @param available the amount of funds that are available for use. Typical reasons that funds + * may be unavailable include fairly new transactions that do not have enough confirmations or + * notes that are tied up because we are awaiting change from a transaction. When a note has + * been spent, its change cannot be used until there are enough confirmations. + */ +data class WalletBalance( + val total: Zatoshi, + val available: Zatoshi +) { + init { + require(total.value >= available.value) { "Wallet total balance must be >= available balance" } + } + + val pending = total - available + + operator fun plus(other: WalletBalance): WalletBalance = + WalletBalance( + total + other.total, + available + other.available + ) +} diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/type/WalletTypes.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/type/WalletTypes.kt index b7ebbbc1..a6abeb55 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/type/WalletTypes.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/type/WalletTypes.kt @@ -1,34 +1,5 @@ package cash.z.ecc.android.sdk.type -import cash.z.ecc.android.sdk.model.Zatoshi - -/** - * Data structure to hold the total and available balance of the wallet. This is what is - * received on the balance channel. - * - * @param total the total balance, ignoring funds that cannot be used. - * @param available the amount of funds that are available for use. Typical reasons that funds - * may be unavailable include fairly new transactions that do not have enough confirmations or - * notes that are tied up because we are awaiting change from a transaction. When a note has - * been spent, its change cannot be used until there are enough confirmations. - */ -data class WalletBalance( - val total: Zatoshi, - val available: Zatoshi -) { - init { - require(total.value >= available.value) { "Wallet total balance must be >= available balance" } - } - - val pending = total - available - - operator fun plus(other: WalletBalance): WalletBalance = - WalletBalance( - total + other.total, - available + other.available - ) -} - /** * Model object for holding a wallet birthday. * diff --git a/sdk-lib/src/test/java/cash/z/ecc/android/sdk/ext/ConversionsTest.kt b/sdk-lib/src/test/java/cash/z/ecc/android/sdk/ext/ConversionsTest.kt index 885f4709..76a5bdbd 100644 --- a/sdk-lib/src/test/java/cash/z/ecc/android/sdk/ext/ConversionsTest.kt +++ b/sdk-lib/src/test/java/cash/z/ecc/android/sdk/ext/ConversionsTest.kt @@ -1,5 +1,6 @@ package cash.z.ecc.android.sdk.ext +import cash.z.ecc.android.sdk.model.Zatoshi import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import java.math.BigDecimal @@ -9,7 +10,7 @@ internal class ConversionsTest { @Test fun `default right padding is 6`() { - assertEquals(1.13.toZec(6), 113000000L.convertZatoshiToZec()) + assertEquals(1.13.toZec(6), Zatoshi(113000000L).convertZatoshiToZec()) assertEquals(1.13.toZec(6), 1.13.toZec()) } @@ -21,12 +22,12 @@ internal class ConversionsTest { @Test fun `toZecString defaults to 6 digits`() { - assertEquals("1.123457", 112345678L.convertZatoshiToZecString()) + assertEquals("1.123457", Zatoshi(112345678L).convertZatoshiToZecString()) } @Test fun `toZecString uses banker's rounding`() { - assertEquals("1.123456", 112345650L.convertZatoshiToZecString()) + assertEquals("1.123456", Zatoshi(112345650L).convertZatoshiToZecString()) } @Test @@ -72,7 +73,7 @@ internal class ConversionsTest { @Test fun `toZecString zatoshi converts`() { - assertEquals("1.123456", 112345650L.convertZatoshiToZecString(6, 0)) + assertEquals("1.123456", Zatoshi(112345650L).convertZatoshiToZecString(6, 0)) } @Test