[#510] Consume Zatoshi from SDK (#514)

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Carter Jernigan 2022-06-23 07:31:16 -04:00 committed by GitHub
parent 22fdc5b717
commit 0ffaab953b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 51 additions and 95 deletions

View File

@ -124,7 +124,7 @@ PLAY_CORE_KTX_VERSION=1.8.1
ZCASH_ANDROID_WALLET_PLUGINS_VERSION=1.0.0
ZCASH_BIP39_VERSION=1.0.2
# TODO [#279]: Revert to stable SDK before app release
ZCASH_SDK_VERSION=1.6.0-beta01-SNAPSHOT
ZCASH_SDK_VERSION=1.7.0-beta01-SNAPSHOT
ZXING_VERSION=3.5.0

View File

@ -1,12 +0,0 @@
package cash.z.ecc.sdk.model
import kotlin.test.assertFailsWith
class ZatoshiTest {
@kotlin.test.Test
fun minValue() {
assertFailsWith<IllegalArgumentException> {
Zatoshi(-1)
}
}
}

View File

@ -1,6 +1,7 @@
package cash.z.ecc.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.fixture.Zip321UriBuildFixture
import cash.z.ecc.sdk.fixture.Zip321UriParseFixture
import kotlinx.coroutines.ExperimentalCoroutinesApi

View File

@ -7,7 +7,7 @@ import cash.z.ecc.sdk.model.ZecSend
fun Synchronizer.send(spendingKey: String, send: ZecSend) = sendToAddress(
spendingKey,
send.amount.value,
send.amount,
send.destination.address,
send.memo.value
)

View File

@ -1,6 +1,6 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.Zatoshi
object ZatoshiFixture {
@Suppress("MagicNumber")

View File

@ -1,7 +1,7 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage

View File

@ -1,8 +1,8 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
object ZecSendFixture {

View File

@ -1,7 +1,7 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
import kotlinx.coroutines.runBlocking

View File

@ -1,7 +1,7 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage

View File

@ -1,8 +0,0 @@
package cash.z.ecc.sdk.model
import cash.z.ecc.android.sdk.type.WalletBalance
// These go away if we update WalletBalance to expose a Zatoshi field type instead of long
val WalletBalance.total get() = Zatoshi(totalZatoshi.coerceAtLeast(0))
val WalletBalance.available get() = Zatoshi(availableZatoshi.coerceAtLeast(0))
val WalletBalance.pending get() = Zatoshi(pendingZatoshi.coerceAtLeast(0))

View File

@ -1,13 +0,0 @@
package cash.z.ecc.sdk.model
/**
*
*/
@JvmInline
value class Zatoshi(val value: Long) {
init {
require(value >= 0)
}
companion object
}

View File

@ -1,5 +1,6 @@
package cash.z.ecc.sdk.model
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.fixture.Zip321UriBuildFixture
import cash.z.ecc.sdk.fixture.Zip321UriParseFixture

View File

@ -1,5 +1,7 @@
package cash.z.ecc.sdk.model
import cash.z.ecc.android.sdk.model.Zatoshi
data class ZecSend(val destination: WalletAddress, val amount: Zatoshi, val memo: Memo) {
companion object
}

View File

@ -4,16 +4,13 @@ import android.content.Context
import android.content.res.Configuration
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.ext.Conversions
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.Zatoshi
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import java.math.BigDecimal
import java.util.Locale
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
class ZecStringTest {
@ -93,17 +90,10 @@ class ZecStringTest {
assertNull(Zatoshi.fromZecString(context, "1,234,", EN_US_MONETARY_SEPARATORS))
}
// TODO [472]: https://github.com/zcash/zcash-android-wallet-sdk/issues/472
@Test
@SmallTest
fun overflow_number_test() {
assertNotNull(Zatoshi.fromZecString(context, "1", EN_US_MONETARY_SEPARATORS))
assertNotNull(Zatoshi.fromZecString(context, "1,000", EN_US_MONETARY_SEPARATORS))
assertNotNull(Zatoshi.fromZecString(context, "10,000,000,000", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "100,000,000,000", EN_US_MONETARY_SEPARATORS))
val overflowCausingNumber = 100000000000L
assertTrue(BigDecimal(overflowCausingNumber).times(Conversions.ONE_ZEC_IN_ZATOSHI) > BigDecimal(Long.MAX_VALUE))
assertNull(Zatoshi.fromZecString(context, overflowCausingNumber.toString(), EN_US_MONETARY_SEPARATORS))
assertNotNull(Zatoshi.fromZecString(context, "21,000,000", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "21,000,001", EN_US_MONETARY_SEPARATORS))
}
}

View File

@ -1,11 +1,11 @@
package cash.z.ecc.sdk.ext.ui
import android.content.Context
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.ext.ui.model.fromZecString
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import kotlinx.coroutines.runBlocking

View File

@ -1,11 +1,10 @@
package cash.z.ecc.sdk.ext.ui.model
import android.content.Context
import cash.z.ecc.android.sdk.ext.Conversions
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import cash.z.ecc.android.sdk.ext.convertZecToZatoshi
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.ZecStringExt
import cash.z.ecc.sdk.model.Zatoshi
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
@ -56,7 +55,7 @@ private const val DECIMALS = 8
// TODO [#412]: https://github.com/zcash/zcash-android-wallet-sdk/issues/412
// The SDK needs to fix the API for currency conversion
fun Zatoshi.toZecString() = value.convertZatoshiToZecString(DECIMALS, DECIMALS)
fun Zatoshi.toZecString() = convertZatoshiToZecString(DECIMALS, DECIMALS)
/*
* ZEC is our own currency, so there's not going to be an existing localization that matches it perfectly.
@ -99,11 +98,10 @@ fun Zatoshi.Companion.fromZecString(
null
}
// TODO [472]: https://github.com/zcash/zcash-android-wallet-sdk/issues/472
// temporary workaround to prevent SDK to returns us negative result
if (bigDecimal?.times(Conversions.ONE_ZEC_IN_ZATOSHI)?.compareTo(BigDecimal(Long.MAX_VALUE)) ?: 0 > 0) {
return null
@Suppress("SwallowedException")
return try {
bigDecimal.convertZecToZatoshi()
} catch (e: IllegalArgumentException) {
null
}
return Zatoshi(bigDecimal.convertZecToZatoshi())
}

View File

@ -9,10 +9,10 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextClearance
import androidx.compose.ui.test.performTextInput
import androidx.test.filters.MediumTest
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.fixture.WalletAddressFixture
import cash.z.ecc.sdk.fixture.ZecRequestFixture
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
import co.electriccoin.zcash.test.UiTestPrerequisites

View File

@ -10,13 +10,13 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextClearance
import androidx.compose.ui.test.performTextInput
import androidx.test.filters.MediumTest
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.fixture.MemoFixture
import cash.z.ecc.sdk.fixture.WalletAddressFixture
import cash.z.ecc.sdk.fixture.ZatoshiFixture
import cash.z.ecc.sdk.fixture.ZecRequestFixture
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.R

View File

@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.fixture
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.type.WalletBalance
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
@ -12,9 +13,9 @@ object WalletSnapshotFixture {
fun new(
status: Synchronizer.Status = Synchronizer.Status.SYNCED,
processorInfo: CompactBlockProcessor.ProcessorInfo = CompactBlockProcessor.ProcessorInfo(),
orchardBalance: WalletBalance = WalletBalance(5, 2),
saplingBalance: WalletBalance = WalletBalance(4, 4),
transparentBalance: WalletBalance = WalletBalance(8, 1),
orchardBalance: WalletBalance = WalletBalance(Zatoshi(5), Zatoshi(2)),
saplingBalance: WalletBalance = WalletBalance(Zatoshi(4), Zatoshi(4)),
transparentBalance: WalletBalance = WalletBalance(Zatoshi(8), Zatoshi(1)),
pendingCount: Int = 0
) = WalletSnapshot(status, processorInfo, orchardBalance, saplingBalance, transparentBalance, pendingCount)
}

View File

@ -3,8 +3,8 @@ package co.electriccoin.zcash.ui.screen.home.model
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.type.WalletBalance
import cash.z.ecc.sdk.model.Zatoshi
// TODO [#292]: Should be moved to SDK-EXT-UI module.
data class WalletSnapshot(
@ -16,24 +16,16 @@ data class WalletSnapshot(
val pendingCount: Int
) {
// Note: the wallet is effectively empty if it cannot cover the miner's fee
val hasFunds = saplingBalance.availableZatoshi >
(ZcashSdk.MINERS_FEE_ZATOSHI.toDouble() / ZcashSdk.ZATOSHI_PER_ZEC) // 0.00001
val hasSaplingBalance = saplingBalance.totalZatoshi > 0
val hasFunds = saplingBalance.available.value >
(ZcashSdk.MINERS_FEE.value.toDouble() / Zatoshi.ZATOSHI_PER_ZEC) // 0.00001
val hasSaplingBalance = saplingBalance.total.value > 0
val isSendEnabled: Boolean get() = status == Synchronizer.Status.SYNCED && hasFunds
}
fun WalletSnapshot.totalBalance(): Zatoshi {
val total = (orchardBalance + saplingBalance + transparentBalance).totalZatoshi
fun WalletSnapshot.totalBalance() = orchardBalance.total + saplingBalance.total + transparentBalance.total
return Zatoshi(total.coerceAtLeast(0))
}
fun WalletSnapshot.spendableBalance(): Zatoshi {
// Note that considering both to be spendable is subject to change.
// The user experience could be confusing, and in the future we might prefer to ask users
// to transfer their balance to the latest balance type to make it spendable.
val total = (orchardBalance + saplingBalance).totalZatoshi
return Zatoshi(total.coerceAtLeast(0))
}
// Note that considering both to be spendable is subject to change.
// The user experience could be confusing, and in the future we might prefer to ask users
// to transfer their balance to the latest balance type to make it spendable.
fun WalletSnapshot.spendableBalance() = orchardBalance.available + saplingBalance.available

View File

@ -30,7 +30,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.sdk.db.entity.Transaction
import cash.z.ecc.sdk.ext.ui.model.toZecString
import cash.z.ecc.sdk.model.total
import co.electriccoin.zcash.crash.android.CrashReporter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT

View File

@ -11,6 +11,7 @@ import cash.z.ecc.android.sdk.db.entity.PendingTransaction
import cash.z.ecc.android.sdk.db.entity.Transaction
import cash.z.ecc.android.sdk.db.entity.isMined
import cash.z.ecc.android.sdk.db.entity.isSubmitSuccess
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.sdk.model.PersistableWallet
@ -256,13 +257,17 @@ private fun Synchronizer.toWalletSnapshot() =
.count {
it.isSubmitSuccess() && !it.isMined()
}
val orchardBalance = flows[2] as WalletBalance?
val saplingBalance = flows[3] as WalletBalance?
val transparentBalance = flows[4] as WalletBalance?
WalletSnapshot(
status = flows[0] as Synchronizer.Status,
processorInfo = flows[1] as CompactBlockProcessor.ProcessorInfo,
orchardBalance = flows[2] as WalletBalance,
saplingBalance = flows[3] as WalletBalance,
transparentBalance = flows[4] as WalletBalance,
pendingCount = pendingCount
flows[0] as Synchronizer.Status,
flows[1] as CompactBlockProcessor.ProcessorInfo,
orchardBalance ?: WalletBalance(Zatoshi(0), Zatoshi(0)),
saplingBalance ?: WalletBalance(Zatoshi(0), Zatoshi(0)),
transparentBalance ?: WalletBalance(Zatoshi(0), Zatoshi(0)),
pendingCount
)
}

View File

@ -26,13 +26,13 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.ZecStringExt
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.ext.ui.model.ZecString
import cash.z.ecc.sdk.ext.ui.model.fromZecString
import cash.z.ecc.sdk.fixture.WalletAddressFixture
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
import co.electriccoin.zcash.ui.R

View File

@ -1,9 +1,9 @@
package co.electriccoin.zcash.ui.screen.send.ext
import androidx.compose.runtime.saveable.mapSaver
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import kotlinx.coroutines.runBlocking

View File

@ -30,6 +30,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ext.ui.ZecSendExt
import cash.z.ecc.sdk.ext.ui.ZecStringExt
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
@ -37,7 +38,6 @@ import cash.z.ecc.sdk.ext.ui.model.ZecString
import cash.z.ecc.sdk.ext.ui.model.toZecString
import cash.z.ecc.sdk.fixture.ZatoshiFixture
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT