From 9b2bad6f102ce25345542f653ae15f264d4b1e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Honza=20Rychnovsk=C3=BD?= Date: Fri, 26 Apr 2024 13:02:07 +0200 Subject: [PATCH] Add zec.rocks lightwalletd server options (#1401) - Default wallet option changed to zec.rocks:443 - Changleog update --- CHANGELOG.md | 4 + .../ui/common/viewmodel/WalletViewModel.kt | 5 +- .../chooseserver/AvailableServerProvider.kt | 44 ++-- .../chooseserver/view/ChooseServerView.kt | 224 ++++++++++-------- 4 files changed, 160 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33cc3144..03a635fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ directly impact users rather than highlighting other key architectural updates.* ## [Unreleased] +### Changed +- We have added one more group of server options (zec.rocks) for increased coverage and reliability +- zec.rocks:443 is now default wallet option + ## [1.0 (630)] - 2024-04-24 ### Changed diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/viewmodel/WalletViewModel.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/viewmodel/WalletViewModel.kt index 40464f45..ce11bef3 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/viewmodel/WalletViewModel.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/viewmodel/WalletViewModel.kt @@ -21,9 +21,7 @@ import cash.z.ecc.android.sdk.model.WalletBalance import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.model.ZcashNetwork import cash.z.ecc.android.sdk.tool.DerivationTool -import cash.z.ecc.sdk.extension.defaultForNetwork import cash.z.ecc.sdk.type.fromResources -import co.electriccoin.lightwallet.client.model.LightWalletEndpoint import co.electriccoin.zcash.global.getInstance import co.electriccoin.zcash.spackle.Twig import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT @@ -42,6 +40,7 @@ import co.electriccoin.zcash.ui.preference.StandardPreferenceSingleton import co.electriccoin.zcash.ui.screen.account.ext.TransactionOverviewExt import co.electriccoin.zcash.ui.screen.account.ext.getSortHeight import co.electriccoin.zcash.ui.screen.account.state.TransactionHistorySyncState +import co.electriccoin.zcash.ui.screen.chooseserver.AvailableServerProvider import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -295,7 +294,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application) PersistableWallet.new( application = application, zcashNetwork = zcashNetwork, - endpoint = LightWalletEndpoint.defaultForNetwork(zcashNetwork), + endpoint = AvailableServerProvider.getDefaultServer(zcashNetwork), walletInitMode = WalletInitMode.NewWallet ) persistWallet(newWallet) diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/AvailableServerProvider.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/AvailableServerProvider.kt index 00ac7b07..402504b7 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/AvailableServerProvider.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/AvailableServerProvider.kt @@ -1,7 +1,6 @@ package co.electriccoin.zcash.ui.screen.chooseserver import cash.z.ecc.android.sdk.model.ZcashNetwork -import cash.z.ecc.sdk.extension.Mainnet import cash.z.ecc.sdk.extension.Testnet import co.electriccoin.lightwallet.client.model.LightWalletEndpoint import kotlinx.collections.immutable.toImmutableList @@ -9,20 +8,14 @@ import kotlinx.collections.immutable.toImmutableList // TODO [#1273]: Add ChooseServer Tests #1273 // TODO [#1273]: https://github.com/Electric-Coin-Company/zashi-android/issues/1273 +@Suppress("UnusedPrivateProperty") object AvailableServerProvider { - // North America | [na.lightwalletd.com](http://na.lightwalletd.com/) | 443 - // South America | [sa.lightwalletd.com](http://sa.lightwalletd.com/) | 443 - // Europe & Africa | [eu.lightwalletd.com](http://eu.lightwalletd.com/) | 443 - // Asia & Oceania | [ai.lightwalletd.com](http://ai.lightwalletd.com/) | 443 - // Plus current network defaults: - // Mainnet: mainnet.lightwalletd.com | 9067 - // Testnet: lightwalletd.testnet.electriccoin.co | 9067 - - private const val NH_HOST_NA = "na.lightwalletd.com" // NON-NLS - private const val NH_HOST_SA = "sa.lightwalletd.com" // NON-NLS - private const val NH_HOST_EU = "eu.lightwalletd.com" // NON-NLS - private const val NH_HOST_AI = "ai.lightwalletd.com" // NON-NLS - private const val NH_PORT = 443 + private const val ZR_HOST = "zec.rocks" // NON-NLS + private const val ZR_HOST_NA = "na.zec.rocks" // NON-NLS + private const val ZR_HOST_SA = "sa.zec.rocks" // NON-NLS + private const val ZR_HOST_EU = "eu.zec.rocks" // NON-NLS + private const val ZR_HOST_AP = "ap.zec.rocks" // NON-NLS + private const val ZR_PORT = 443 private const val YW_HOST_1 = "lwd1.zcash-infra.com" // NON-NLS private const val YW_HOST_2 = "lwd2.zcash-infra.com" // NON-NLS @@ -34,10 +27,24 @@ object AvailableServerProvider { private const val YW_HOST_8 = "lwd8.zcash-infra.com" // NON-NLS private const val YW_PORT = 9067 + // NH servers are currently unused and are subject of removal in the future + private const val NH_HOST_NA = "na.lightwalletd.com" // NON-NLS + private const val NH_HOST_SA = "sa.lightwalletd.com" // NON-NLS + private const val NH_HOST_EU = "eu.lightwalletd.com" // NON-NLS + private const val NH_HOST_AI = "ai.lightwalletd.com" // NON-NLS + private const val NH_PORT = 443 + fun toList(network: ZcashNetwork) = buildList { if (network == ZcashNetwork.Mainnet) { - add(LightWalletEndpoint.Mainnet) + add(LightWalletEndpoint(ZR_HOST, ZR_PORT, true)) + + // Custom server item comes here in the view layer + + add(LightWalletEndpoint(ZR_HOST_NA, ZR_PORT, true)) + add(LightWalletEndpoint(ZR_HOST_SA, ZR_PORT, true)) + add(LightWalletEndpoint(ZR_HOST_EU, ZR_PORT, true)) + add(LightWalletEndpoint(ZR_HOST_AP, ZR_PORT, true)) add(LightWalletEndpoint(YW_HOST_1, YW_PORT, true)) add(LightWalletEndpoint(YW_HOST_2, YW_PORT, true)) @@ -47,15 +54,12 @@ object AvailableServerProvider { add(LightWalletEndpoint(YW_HOST_6, YW_PORT, true)) add(LightWalletEndpoint(YW_HOST_7, YW_PORT, true)) add(LightWalletEndpoint(YW_HOST_8, YW_PORT, true)) - - add(LightWalletEndpoint(NH_HOST_NA, NH_PORT, true)) - add(LightWalletEndpoint(NH_HOST_SA, NH_PORT, true)) - add(LightWalletEndpoint(NH_HOST_EU, NH_PORT, true)) - add(LightWalletEndpoint(NH_HOST_AI, NH_PORT, true)) } else { add(LightWalletEndpoint.Testnet) } }.toImmutableList() + + fun getDefaultServer(zcashNetwork: ZcashNetwork): LightWalletEndpoint = toList(zcashNetwork).first() } // This regex validates server URLs with ports in format: : diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/view/ChooseServerView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/view/ChooseServerView.kt index fba6dd76..edece950 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/view/ChooseServerView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/chooseserver/view/ChooseServerView.kt @@ -1,7 +1,10 @@ +@file:Suppress("TooManyFunctions") + package co.electriccoin.zcash.ui.screen.chooseserver.view import androidx.compose.animation.animateContentSize import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -11,6 +14,9 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.DividerDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -25,7 +31,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import cash.z.ecc.android.sdk.internal.Twig import cash.z.ecc.android.sdk.model.PersistableWallet @@ -41,7 +46,6 @@ import co.electriccoin.zcash.ui.design.component.GradientSurface import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.RadioButton import co.electriccoin.zcash.ui.design.component.SmallTopAppBar -import co.electriccoin.zcash.ui.design.component.SubHeader import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.screen.chooseserver.ChooseServerTag import co.electriccoin.zcash.ui.screen.chooseserver.validateCustomServerValue @@ -70,7 +74,7 @@ private fun PreviewChooseServer() { } @Composable -@Suppress("LongParameterList") +@Suppress("LongMethod", "LongParameterList") fun ChooseServer( availableServers: ImmutableList, onBack: () -> Unit, @@ -82,80 +86,6 @@ fun ChooseServer( isShowingSuccessDialog: Boolean, setShowSuccessDialog: (Boolean) -> Unit, walletRestoringState: WalletRestoringState, -) { - Scaffold( - topBar = { - ChooseServerTopAppBar( - onBack = onBack, - showRestoring = walletRestoringState == WalletRestoringState.RESTORING, - ) - } - ) { paddingValues -> - ChooseServerMainContent( - modifier = - Modifier - .verticalScroll( - rememberScrollState() - ) - .padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding(), - start = ZcashTheme.dimens.screenHorizontalSpacingRegular, - end = ZcashTheme.dimens.screenHorizontalSpacingRegular - ) - .fillMaxWidth(), - availableServers = availableServers, - onServerChange = onServerChange, - setShowErrorDialog = setShowErrorDialog, - validationResult = validationResult, - wallet = wallet, - ) - - // Show validation popups - if (isShowingErrorDialog && validationResult is ServerValidation.InValid) { - ValidationErrorDialog( - reason = validationResult.reason.message, - onDone = { setShowErrorDialog(false) } - ) - } else if (isShowingSuccessDialog) { - SaveSuccessDialog( - onDone = { setShowSuccessDialog(false) } - ) - } - } -} - -@Composable -private fun ChooseServerTopAppBar( - onBack: () -> Unit, - showRestoring: Boolean -) { - SmallTopAppBar( - restoringLabel = - if (showRestoring) { - stringResource(id = R.string.restoring_wallet_label) - } else { - null - }, - modifier = Modifier.testTag(ChooseServerTag.CHOOSE_SERVER_TOP_APP_BAR), - showTitleLogo = true, - backText = stringResource(id = R.string.choose_server_back).uppercase(), - backContentDescriptionText = stringResource(R.string.choose_server_back_content_description), - onBack = onBack, - ) -} - -const val CUSTOM_SERVER_OPTION_INDEX = 1 - -@Composable -@Suppress("LongMethod", "LongParameterList") -private fun ChooseServerMainContent( - availableServers: ImmutableList, - onServerChange: (LightWalletEndpoint) -> Unit, - validationResult: ServerValidation, - wallet: PersistableWallet, - modifier: Modifier = Modifier, - setShowErrorDialog: (Boolean) -> Unit, ) { val options = availableServers.toMutableList().apply { @@ -193,27 +123,84 @@ private fun ChooseServerMainContent( mutableStateOf(initialCustomServerValue) } - Column(modifier = modifier) { - Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) - - SubHeader( - text = stringResource(id = R.string.choose_server_title), - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() - ) - - Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) - - ServerList( + Scaffold( + topBar = { + ChooseServerTopAppBar( + onBack = onBack, + showRestoring = walletRestoringState == WalletRestoringState.RESTORING, + ) + }, + bottomBar = { + ChooseServerBottomBar( + customServerValue = customServerValue, + onServerChange = onServerChange, + options = options, + selectedOption = selectedOption, + setShowErrorDialog = setShowErrorDialog, + validationResult = validationResult, + wallet = wallet + ) + } + ) { paddingValues -> + ChooseServerMainContent( + customServerValue = customServerValue, + modifier = + Modifier + .verticalScroll( + rememberScrollState() + ) + .padding( + top = paddingValues.calculateTopPadding(), + bottom = paddingValues.calculateBottomPadding(), + start = ZcashTheme.dimens.screenHorizontalSpacingRegular, + end = ZcashTheme.dimens.screenHorizontalSpacingRegular + ) + .fillMaxWidth(), options = options, selectedOption = selectedOption, - setSelectedOption = setSelectedOption, - customServerValue = customServerValue, setCustomServerValue = setCustomServerValue, - modifier = Modifier.fillMaxWidth() + setSelectedOption = setSelectedOption, ) - Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + // Show validation popups + if (isShowingErrorDialog && validationResult is ServerValidation.InValid) { + ValidationErrorDialog( + reason = validationResult.reason.message, + onDone = { setShowErrorDialog(false) } + ) + } else if (isShowingSuccessDialog) { + SaveSuccessDialog( + onDone = { setShowSuccessDialog(false) } + ) + } + } +} + +@Composable +@Suppress("LongParameterList") +fun ChooseServerBottomBar( + customServerValue: String, + onServerChange: (LightWalletEndpoint) -> Unit, + options: ImmutableList, + selectedOption: Int, + setShowErrorDialog: (Boolean) -> Unit, + validationResult: ServerValidation, + wallet: PersistableWallet, + modifier: Modifier = Modifier, +) { + Column( + modifier = + modifier.then( + Modifier + .background(MaterialTheme.colorScheme.surface) + ) + ) { + HorizontalDivider( + thickness = DividerDefaults.Thickness, + color = ZcashTheme.colors.dividerColor + ) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) SaveButton( enabled = validationResult != ServerValidation.Running, @@ -227,13 +214,62 @@ private fun ChooseServerMainContent( }, setShowErrorDialog = setShowErrorDialog, selectedOption = selectedOption, - modifier = Modifier.padding(horizontal = ZcashTheme.dimens.spacingUpLarge) + modifier = Modifier.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingBig) ) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingHuge)) } } +@Composable +private fun ChooseServerTopAppBar( + onBack: () -> Unit, + showRestoring: Boolean +) { + SmallTopAppBar( + titleText = stringResource(id = R.string.choose_server_title), + restoringLabel = + if (showRestoring) { + stringResource(id = R.string.restoring_wallet_label) + } else { + null + }, + modifier = Modifier.testTag(ChooseServerTag.CHOOSE_SERVER_TOP_APP_BAR), + showTitleLogo = true, + backText = stringResource(id = R.string.choose_server_back).uppercase(), + backContentDescriptionText = stringResource(R.string.choose_server_back_content_description), + onBack = onBack, + ) +} + +const val CUSTOM_SERVER_OPTION_INDEX = 1 + +@Composable +@Suppress("LongParameterList") +private fun ChooseServerMainContent( + customServerValue: String, + options: ImmutableList, + selectedOption: Int, + setCustomServerValue: (String) -> Unit, + setSelectedOption: (Int) -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier) { + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) + + ServerList( + options = options, + selectedOption = selectedOption, + setSelectedOption = setSelectedOption, + customServerValue = customServerValue, + setCustomServerValue = setCustomServerValue, + modifier = Modifier.fillMaxWidth() + ) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) + } +} + @OptIn(ExperimentalFoundationApi::class) @Composable @Suppress("LongParameterList")