[#223] fromZecString reject bad input.

- Implementing regex solution for validation of input ZecAmount after confirm button is pressed.
- Added also unit tests for this new feature.
- Move necessary components from sdk-ext-lib to sdk-ext-ui module.
- Align implementation with comments form PR.
- Fix name of run configuration.
- Ensure consistent behavior of tests.
This commit is contained in:
Honza Rychnovsky 2022-04-08 14:33:08 +02:00 committed by GitHub
parent 9485a7d4c3
commit 4e5e5c4ab7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 302 additions and 160 deletions

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="sdk-ext-ui:connectedCheck" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<module name="zcash-android-app.sdk-ext-ui" />
<configuration default="false" name="sdk-ext-ui-lib:connectedCheck" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<module name="zcash-android-app.sdk-ext-ui-lib" />
<option name="TESTING_TYPE" value="0" />
<option name="METHOD_NAME" value="" />
<option name="CLASS_NAME" value="" />

View File

@ -148,6 +148,7 @@ dependencies {
androidTestImplementation(libs.bundles.androidx.test)
androidTestImplementation(projects.sdkExtLib)
androidTestImplementation(projects.spackleLib)
androidTestImplementation(projects.sdkExtUiLib)
if (isOrchestratorEnabled) {
androidTestUtil(libs.androidx.test.orchestrator) {

View File

@ -23,9 +23,9 @@ import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import androidx.test.runner.screenshot.Screenshot
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.fixture.SeedPhraseFixture
import cash.z.ecc.sdk.fixture.WalletAddressFixture
import cash.z.ecc.sdk.model.MonetarySeparators
import co.electriccoin.zcash.app.test.EccScreenCaptureProcessor
import co.electriccoin.zcash.app.test.getStringResource
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil

View File

@ -1,78 +0,0 @@
package cash.z.ecc.sdk.model
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertNull
class ZecStringTest {
companion object {
private val EN_US_MONETARY_SEPARATORS = MonetarySeparators(',', '.')
}
@Test
fun empty_string() {
val actual = Zatoshi.fromZecString("", EN_US_MONETARY_SEPARATORS)
val expected = null
assertEquals(expected, actual)
}
@Test
fun decimal_monetary_separator() {
val actual = Zatoshi.fromZecString("1.13", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000L)
assertEquals(expected, actual)
}
@Test
fun comma_grouping_separator() {
val actual = Zatoshi.fromZecString("1,130", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000000L)
assertEquals(expected, actual)
}
@Test
fun decimal_monetary_and() {
val actual = Zatoshi.fromZecString("1,130", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000000L)
assertEquals(expected, actual)
}
@Test
fun toZecString() {
val expected = "1.13000000"
val actual = Zatoshi(113000000).toZecString()
assertEquals(expected, actual)
}
@Test
@Ignore("https://github.com/zcash/zcash-android-wallet-sdk/issues/412")
fun round_trip() {
val expected = Zatoshi(113000000L)
val actual = Zatoshi.fromZecString(expected.toZecString(), EN_US_MONETARY_SEPARATORS)
assertEquals(expected, actual)
}
@Test
@Ignore("https://github.com/zcash/secant-android-wallet/issues/223")
fun parse_bad_string() {
val actual = Zatoshi.fromZecString("asdf", EN_US_MONETARY_SEPARATORS)
assertNull(actual)
}
@Test
@Ignore("https://github.com/zcash/secant-android-wallet/issues/223")
fun parse_bad_number() {
val actual = Zatoshi.fromZecString("1.2,3,4", EN_US_MONETARY_SEPARATORS)
assertNull(actual)
}
}

View File

@ -1,47 +1,5 @@
package cash.z.ecc.sdk.model
import kotlinx.coroutines.runBlocking
data class ZecSend(val destination: WalletAddress, val amount: Zatoshi, val memo: Memo) {
companion object
}
fun ZecSend.Companion.new(
destinationString: String,
zecString: String,
memoString: String,
monetarySeparators: MonetarySeparators
): ZecSendValidation {
// This runBlocking shouldn't have a performance impact, since everything needs to be loaded at this point.
// However it would be better to eliminate it entirely.
val destination = runBlocking { WalletAddress.Unified.new(destinationString) }
val amount = Zatoshi.fromZecString(zecString, monetarySeparators)
val memo = Memo(memoString)
val validationErrors = buildSet {
if (null == amount) {
add(ZecSendValidation.Invalid.ValidationError.INVALID_AMOUNT)
}
// TODO [#250]: Implement all validation
// TODO [#342]: https://github.com/zcash/zcash-android-wallet-sdk/issues/342
}
return if (validationErrors.isEmpty()) {
ZecSendValidation.Valid(ZecSend(destination, amount!!, memo))
} else {
ZecSendValidation.Invalid(validationErrors)
}
}
sealed class ZecSendValidation {
data class Valid(val zecSend: ZecSend) : ZecSendValidation()
data class Invalid(val validationErrors: Set<ValidationError>) : ZecSendValidation() {
enum class ValidationError {
INVALID_ADDRESS,
INVALID_AMOUNT,
INVALID_MEMO
}
}
}

View File

@ -11,11 +11,15 @@ android {
allWarningsAsErrors = project.property("ZCASH_IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
freeCompilerArgs = freeCompilerArgs.plus("-Xopt-in=kotlin.RequiresOptIn")
}
resourcePrefix = "co_electriccoin_zcash_"
}
dependencies {
implementation(projects.sdkExtLib)
implementation(libs.kotlinx.coroutines.core)
androidTestImplementation(libs.bundles.androidx.test)
androidTestImplementation(libs.kotlin.test)

View File

@ -0,0 +1,90 @@
package cash.z.ecc.sdk.ext.ui.model
import android.content.Context
import android.content.res.Configuration
import androidx.test.core.app.ApplicationProvider
import cash.z.ecc.sdk.model.Zatoshi
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import java.util.Locale
import kotlin.test.assertNull
class ZecStringTest {
companion object {
private val EN_US_MONETARY_SEPARATORS = MonetarySeparators(',', '.')
private val context = run {
val applicationContext = ApplicationProvider.getApplicationContext<Context>()
val enUsConfiguration = Configuration(applicationContext.resources.configuration).apply {
setLocale(Locale.US)
}
applicationContext.createConfigurationContext(enUsConfiguration)
}
}
@Test
fun empty_string() {
val actual = Zatoshi.fromZecString(context, "", EN_US_MONETARY_SEPARATORS)
val expected = null
assertEquals(expected, actual)
}
@Test
fun decimal_monetary_separator() {
val actual = Zatoshi.fromZecString(context, "1.13", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000L)
assertEquals(expected, actual)
}
@Test
fun comma_grouping_separator() {
val actual = Zatoshi.fromZecString(context, "1,130", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000000L)
assertEquals(expected, actual)
}
@Test
fun decimal_monetary_and() {
val actual = Zatoshi.fromZecString(context, "1,130", EN_US_MONETARY_SEPARATORS)
val expected = Zatoshi(113000000000L)
assertEquals(expected, actual)
}
@Test
@Ignore("https://github.com/zcash/zcash-android-wallet-sdk/issues/412")
fun toZecString() {
val expected = "1.13000000"
val actual = Zatoshi(113000000).toZecString()
assertEquals(expected, actual)
}
@Test
@Ignore("https://github.com/zcash/zcash-android-wallet-sdk/issues/412")
fun round_trip() {
val expected = Zatoshi(113000000L)
val actual = Zatoshi.fromZecString(context, expected.toZecString(), EN_US_MONETARY_SEPARATORS)
assertEquals(expected, actual)
}
@Test
fun parse_bad_string() {
assertNull(Zatoshi.fromZecString(context, "", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "+@#$~^&*=", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "asdf", EN_US_MONETARY_SEPARATORS))
}
@Test
fun parse_invalid_numbers() {
assertNull(Zatoshi.fromZecString(context, "", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "1,2", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "1,23,", EN_US_MONETARY_SEPARATORS))
assertNull(Zatoshi.fromZecString(context, "1,234,", EN_US_MONETARY_SEPARATORS))
}
}

View File

@ -3,8 +3,8 @@ package cash.z.ecc.sdk.ext.ui.regex
import androidx.test.filters.SmallTest
import cash.z.ecc.sdk.ext.ui.R
import cash.z.ecc.sdk.ext.ui.ZecStringExt
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
import cash.z.ecc.sdk.ext.ui.test.getStringResourceWithArgs
import cash.z.ecc.sdk.model.MonetarySeparators
import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
@ -18,7 +18,17 @@ class ZecStringExtTest {
private fun getContinuousRegex(): Regex {
return getStringResourceWithArgs(
R.string.zec_amount_regex_continuous_filter,
R.string.co_electriccoin_zcash_zec_amount_regex_continuous_filter,
arrayOf(
EN_US_SEPARATORS.grouping,
EN_US_SEPARATORS.decimal
)
).toRegex()
}
private fun getConfirmRegex(): Regex {
return getStringResourceWithArgs(
R.string.co_electriccoin_zcash_zec_amount_regex_confirm_filter,
arrayOf(
EN_US_SEPARATORS.grouping,
EN_US_SEPARATORS.decimal
@ -28,9 +38,9 @@ class ZecStringExtTest {
@Test
@SmallTest
fun check_regex_validity() {
fun check_continuous_regex_validity() {
val regexString = getStringResourceWithArgs(
R.string.zec_amount_regex_continuous_filter,
R.string.co_electriccoin_zcash_zec_amount_regex_continuous_filter,
arrayOf(
EN_US_SEPARATORS.grouping,
EN_US_SEPARATORS.decimal
@ -48,7 +58,27 @@ class ZecStringExtTest {
@Test
@SmallTest
fun check_regex_functionality_valid_inputs() {
fun check_confirm_regex_validity() {
val regexString = getStringResourceWithArgs(
R.string.co_electriccoin_zcash_zec_amount_regex_confirm_filter,
arrayOf(
EN_US_SEPARATORS.grouping,
EN_US_SEPARATORS.decimal
)
)
assertNotNull(regexString)
val regexAmountChecker = regexString.toRegex()
regexAmountChecker.also {
assertNotNull(regexAmountChecker)
assertTrue(regexAmountChecker.pattern.isNotEmpty())
}
}
@Test
@SmallTest
fun check_continuous_regex_functionality_valid_inputs() {
getContinuousRegex().also {
assertTrue(it.matches(""))
assertTrue(it.matches("123"))
@ -66,7 +96,7 @@ class ZecStringExtTest {
@Test
@SmallTest
fun check_regex_functionality_invalid_inputs() {
fun check_continuous_regex_functionality_invalid_inputs() {
getContinuousRegex().also {
assertFalse(it.matches("aaa"))
assertFalse(it.matches("123aaa"))
@ -80,6 +110,44 @@ class ZecStringExtTest {
}
}
@Test
@SmallTest
fun check_confirm_regex_functionality_valid_inputs() {
getConfirmRegex().also {
assertTrue(it.matches("123"))
assertTrue(it.matches(".123"))
assertTrue(it.matches("1,234"))
assertTrue(it.matches("1,234,567,890"))
assertTrue(it.matches("1.2"))
assertTrue(it.matches("123.4"))
assertTrue(it.matches("1.234"))
assertTrue(it.matches("1,123."))
assertTrue(it.matches("1,234.567"))
assertTrue(it.matches("1,234,567.890"))
}
}
@Test
@SmallTest
fun check_confirm_regex_functionality_invalid_inputs() {
getContinuousRegex().also {
assertFalse(it.matches("+@#$~^&*="))
assertFalse(it.matches("asdf"))
assertFalse(it.matches(".."))
assertFalse(it.matches(","))
assertFalse(it.matches(",,"))
assertFalse(it.matches(",."))
assertFalse(it.matches(".,"))
assertFalse(it.matches(",123"))
assertFalse(it.matches("1,2,3"))
assertFalse(it.matches("1.2,3,4"))
assertFalse(it.matches("123,,456"))
assertFalse(it.matches("123..456"))
assertFalse(it.matches("1.234,567"))
assertFalse(it.matches("1.234,567,890"))
}
}
@Test
@SmallTest
fun check_digits_between_grouping_separators_valid_test() {

View File

@ -0,0 +1,54 @@
package cash.z.ecc.sdk.ext.ui
import android.content.Context
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
object ZecSendExt {
fun new(
context: Context,
destinationString: String,
zecString: String,
memoString: String,
monetarySeparators: MonetarySeparators
): ZecSendValidation {
// This runBlocking shouldn't have a performance impact, since everything needs to be loaded at this point.
// However it would be better to eliminate it entirely.
val destination = runBlocking { WalletAddress.Unified.new(destinationString) }
val amount = Zatoshi.fromZecString(context, zecString, monetarySeparators)
val memo = Memo(memoString)
val validationErrors = buildSet {
if (null == amount) {
add(ZecSendValidation.Invalid.ValidationError.INVALID_AMOUNT)
}
// TODO [#250]: Implement all validation
// TODO [#342]: https://github.com/zcash/zcash-android-wallet-sdk/issues/342
}
return if (validationErrors.isEmpty()) {
ZecSendValidation.Valid(ZecSend(destination, amount!!, memo))
} else {
ZecSendValidation.Invalid(validationErrors)
}
}
sealed class ZecSendValidation {
data class Valid(val zecSend: ZecSend) : ZecSendValidation()
data class Invalid(val validationErrors: Set<ValidationError>) : ZecSendValidation() {
enum class ValidationError {
INVALID_ADDRESS,
INVALID_AMOUNT,
INVALID_MEMO
}
}
}
}

View File

@ -1,21 +1,21 @@
package cash.z.ecc.sdk.ext.ui
import android.content.Context
import cash.z.ecc.sdk.model.MonetarySeparators
import cash.z.ecc.sdk.ext.ui.model.MonetarySeparators
object ZecStringExt {
private const val DIGITS_BETWEEN_GROUP_SEPARATORS = 3
/**
* Builds filter with current local monetary separators for continuous input checking. Solution
* is build upon regex validation and character checking.
* Builds filter with current local monetary separators for continuous input checking. The
* solution is built upon regex validation and other common string validation checks.
*
* Regex example: ^([0-9]*([0-9]+([,]$|[,][0-9]+))*([.]$|[.][0-9]+)?)?$
* Inputs may differ according to user locale.
*
* Valid amounts: "" . | .123 | 123, | 123. | 123,456 | 123.456 | 123,456.789 | 123,456,789 | 123,456,789.123 | etc.
* Invalid amounts: 123,, | 123,. | 123.. | .123 | ,123 | 123.456.789 | etc.
* Invalid amounts: 123,, | 123,. | 123.. | ,123 | 123.456.789 | etc.
*
* @param context used for loading localized pattern from strings.xml
* @param separators which consist of localized monetary separators
@ -25,7 +25,7 @@ object ZecStringExt {
*/
fun filterContinuous(context: Context, separators: MonetarySeparators, zecString: String): Boolean {
if (!context.getString(
R.string.zec_amount_regex_continuous_filter,
R.string.co_electriccoin_zcash_zec_amount_regex_continuous_filter,
separators.grouping,
separators.decimal
).toRegex().matches(zecString) || !checkFor3Digits(separators, zecString)
@ -54,4 +54,38 @@ object ZecStringExt {
}
return true
}
/**
* Builds filter with current local monetary separators for validation of entered ZEC amount
* after confirm button is pressed. The solution is built upon regex validation and other common
* string validation checks.
*
* Regex example: ^([0-9]{1,3}(?:[,]?[0-9]{3})*)*(?:[0-9]*[.][0-9]*)?$
* Inputs may differ according to user locale.
*
* Valid amounts: 123 | .123 | 123. | 123, | 123.456 | 123,456 | 123,456.789 | 123,456,789 | 123,456,789.123 | etc.
* Invalid amounts: "" | , | . | 123,, | 123,. | 123.. | ,123 | 123.456.789 | etc.
*
* @param context used for loading localized pattern from strings.xml
* @param separators which consist of localized monetary separators
* @param zecString to be validated
*
* @return true in case of validation success, false otherwise
*/
fun filterConfirm(context: Context, separators: MonetarySeparators, zecString: String): Boolean {
if (zecString.isBlank() ||
zecString == separators.grouping.toString() ||
zecString == separators.decimal.toString()
) {
return false
}
return (
context.getString(
R.string.co_electriccoin_zcash_zec_amount_regex_confirm_filter,
separators.grouping,
separators.decimal
).toRegex().matches(zecString) && checkFor3Digits(separators, zecString)
)
}
}

View File

@ -1,7 +1,10 @@
package cash.z.ecc.sdk.model
package cash.z.ecc.sdk.ext.ui.model
import android.content.Context
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import cash.z.ecc.android.sdk.ext.convertZecToZatoshi
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
@ -64,8 +67,12 @@ fun Zatoshi.toZecString() = value.convertZatoshiToZecString(DECIMALS, DECIMALS)
/**
* @return [zecString] parsed into Zatoshi or null if parsing failed.
*/
fun Zatoshi.Companion.fromZecString(zecString: String, monetarySeparators: MonetarySeparators): Zatoshi? {
if (zecString.isBlank()) {
fun Zatoshi.Companion.fromZecString(
context: Context,
zecString: String,
monetarySeparators: MonetarySeparators
): Zatoshi? {
if (!ZecStringExt.filterConfirm(context, monetarySeparators, zecString)) {
return null
}
@ -81,6 +88,7 @@ fun Zatoshi.Companion.fromZecString(zecString: String, monetarySeparators: Monet
roundingMode = RoundingMode.HALF_EVEN // aka Bankers rounding
}
// TODO [#343]: https://github.com/zcash/secant-android-wallet/issues/343
val bigDecimal = try {
decimalFormat.parse(zecString) as BigDecimal
} catch (e: NumberFormatException) {

View File

@ -0,0 +1,4 @@
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="co_electriccoin_zcash_zec_amount_regex_continuous_filter" formatted="true" tools:ignore="TypographyDashes">^([0-9]*([0-9]+([<xliff:g id="group" example=",">%1$s</xliff:g>]$|[<xliff:g id="group" example=",">%1$s</xliff:g>][0-9]+))*([<xliff:g id="dec" example=".">%2$s</xliff:g>]$|[<xliff:g id="dec" example=".">%2$s</xliff:g>][0-9]+)?)?$</string>
<string name="co_electriccoin_zcash_zec_amount_regex_confirm_filter" formatted="true" tools:ignore="TypographyDashes">^([0-9]{1,3}(?:[<xliff:g id="group" example=",">%1$s</xliff:g>]?[0-9]{3})*)*(?:[0-9]*[<xliff:g id="group" example=".">%2$s</xliff:g>][0-9]*)?$</string>
</resources>

View File

@ -1,3 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="zec_amount_regex_continuous_filter" formatted="true" tools:ignore="TypographyDashes">^([0-9]*([0-9]+([<xliff:g id="group" example=",">%1$s</xliff:g>]$|[<xliff:g id="group" example=",">%1$s</xliff:g>][0-9]+))*([<xliff:g id="dec" example=".">%2$s</xliff:g>]$|[<xliff:g id="dec" example=".">%2$s</xliff:g>][0-9]+)?)?$</string>
</resources>

View File

@ -210,7 +210,7 @@ include("build-info-lib")
include("preference-api-lib")
include("preference-impl-android-lib")
include("sdk-ext-lib")
include("sdk-ext-ui")
include("sdk-ext-ui-lib")
include("spackle-lib")
include("ui-design-lib")
include("ui-lib")

View File

@ -63,7 +63,7 @@ dependencies {
implementation(projects.preferenceApiLib)
implementation(projects.preferenceImplAndroidLib)
implementation(projects.sdkExtLib)
implementation(projects.sdkExtUi)
implementation(projects.sdkExtUiLib)
implementation(projects.spackleLib)
implementation(projects.uiDesignLib)

View File

@ -9,9 +9,9 @@ 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.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.MonetarySeparators
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
@ -102,8 +102,8 @@ class RequestViewTest {
composeTestRule.clickCreateAndSend()
assertEquals(1, testSetup.getOnCreateCount())
// e.g. 123,
composeTestRule.setAmount("123${separators.grouping}")
// e.g. 123,456
composeTestRule.setAmount("123${separators.grouping}456")
composeTestRule.clickCreateAndSend()
assertEquals(2, testSetup.getOnCreateCount())

View File

@ -10,12 +10,12 @@ 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.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.MonetarySeparators
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import co.electriccoin.zcash.ui.R

View File

@ -20,7 +20,7 @@ import androidx.compose.ui.Modifier
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.model.toZecString
import cash.z.ecc.sdk.ext.ui.model.toZecString
import cash.z.ecc.sdk.model.total
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT

View File

@ -25,14 +25,14 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
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.MonetarySeparators
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 cash.z.ecc.sdk.model.ZecString
import cash.z.ecc.sdk.model.fromZecString
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.GradientSurface
@ -129,7 +129,7 @@ private fun RequestMainContent(
Spacer(Modifier.fillMaxHeight(MINIMAL_WEIGHT))
val zatoshi = Zatoshi.fromZecString(amountZecString, monetarySeparators)
val zatoshi = Zatoshi.fromZecString(context, amountZecString, monetarySeparators)
PrimaryButton(
onClick = {

View File

@ -28,16 +28,15 @@ 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.sdk.ext.ui.ZecSendExt
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.toZecString
import cash.z.ecc.sdk.fixture.ZatoshiFixture
import cash.z.ecc.sdk.model.Memo
import cash.z.ecc.sdk.model.MonetarySeparators
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecSend
import cash.z.ecc.sdk.model.ZecSendValidation
import cash.z.ecc.sdk.model.ZecString
import cash.z.ecc.sdk.model.new
import cash.z.ecc.sdk.model.toZecString
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.GradientSurface
@ -157,7 +156,9 @@ private fun SendForm(
}
var memoString by rememberSaveable { mutableStateOf(previousZecSend?.memo?.value ?: "") }
var validation by rememberSaveable { mutableStateOf<Set<ZecSendValidation.Invalid.ValidationError>>(emptySet()) }
var validation by rememberSaveable {
mutableStateOf<Set<ZecSendExt.ZecSendValidation.Invalid.ValidationError>>(emptySet())
}
Column(Modifier.fillMaxHeight()) {
Row(Modifier.fillMaxWidth()) {
@ -205,7 +206,8 @@ private fun SendForm(
PrimaryButton(
onClick = {
val zecSendValidation = ZecSend.new(
val zecSendValidation = ZecSendExt.new(
context,
recipientAddressString,
amountZecString,
memoString,
@ -213,8 +215,8 @@ private fun SendForm(
)
when (zecSendValidation) {
is ZecSendValidation.Valid -> onCreateAndSend(zecSendValidation.zecSend)
is ZecSendValidation.Invalid -> validation = zecSendValidation.validationErrors
is ZecSendExt.ZecSendValidation.Valid -> onCreateAndSend(zecSendValidation.zecSend)
is ZecSendExt.ZecSendValidation.Invalid -> validation = zecSendValidation.validationErrors
}
},
text = stringResource(id = R.string.send_create),