Skip to content

Commit

Permalink
catalyst UI improvements (#1275)
Browse files Browse the repository at this point in the history
* disable Catalyst registration for hardware wallets [ch8701]

* improve wording

* flow

* make sure only shelley wallets can vote

* add missing types in TxHistory and use hooks intestead of ecompose

* add additional voting constrains and preliminary registration dates

* add screenshot tip
  • Loading branch information
v-almonacid committed Apr 30, 2021
1 parent cda058a commit 2177abe
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 30 deletions.
11 changes: 10 additions & 1 deletion src/components/Catalyst/Step1.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ const messages = defineMessages({
defaultMessage:
'!!!Before you begin, make sure to download the Catalyst Voting App.',
},
tip: {
id: 'components.catalyst.step1.tip',
defaultMessage:
'!!!Tip: Make sure you know how to take a screenshot with your device, ' +
'so that you can backup your catalyst QR code.',
},
})

const Step1 = ({intl, generateVotingKeys, navigation, fetchUTXOs}) => {
Expand Down Expand Up @@ -72,7 +78,7 @@ const Step1 = ({intl, generateVotingKeys, navigation, fetchUTXOs}) => {
<View style={styles.mb40}>
<Image source={AppDownload} />
</View>
<View style={styles.buttons}>
<View style={[styles.buttons, styles.mb40]}>
<TouchableOpacity onPress={() => openAppStore()}>
<Image style={styles.iOS} source={appstoreBadge} />
</TouchableOpacity>
Expand All @@ -81,6 +87,9 @@ const Step1 = ({intl, generateVotingKeys, navigation, fetchUTXOs}) => {
</TouchableOpacity>
</View>
</View>
<View style={styles.description}>
<Text style={styles.tip}>{intl.formatMessage(messages.tip)}</Text>
</View>
</ScrollView>
<Button
onPress={() => navigation.navigate(CATALYST_ROUTES.STEP2)}
Expand Down
29 changes: 22 additions & 7 deletions src/components/Catalyst/Step5.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,16 @@ const messages = defineMessages({
description: {
id: 'components.catalyst.step5.description',
defaultMessage:
'!!!Enter the spending password to confirm voting registration and ' +
'submit the certificate generated in previous step to blockchain',
'!!!Please enter your spending password again to confirm your voting ' +
'registration and submit the certificate generated in the previous ' +
'step.',
},
bioAuthDescription: {
id: 'components.catalyst.step5.bioAuthDescription',
defaultMessage:
'!!!Please confirm your voting registration. You will be asked to ' +
'authenticate once again to sign and submit the certificate generated ' +
'in the previous step.',
},
})

Expand Down Expand Up @@ -173,12 +181,19 @@ const Step5 = ({
{intl.formatMessage(messages.subTitle)}
</Text>
<Text style={[styles.description, styles.mb70]}>
{intl.formatMessage(messages.description)}
</Text>
<Text small>
{intl.formatMessage(txLabels.fees)}:{' '}
{fees ? formatTokenWithSymbol(fees, defaultAsset) : ''}
{/* eslint-disable indent */
isEasyConfirmationEnabled
? intl.formatMessage(messages.bioAuthDescription)
: intl.formatMessage(messages.description)
/* eslint-enable indent */
}
</Text>
<ValidatedTextInput
value={fees ? formatTokenWithSymbol(fees, defaultAsset) : ''}
label={`${intl.formatMessage(txLabels.fees)}`}
editable={false}
onChangeText={() => ({})}
/>
{!isEasyConfirmationEnabled && (
<View>
<ValidatedTextInput
Expand Down
3 changes: 3 additions & 0 deletions src/components/Catalyst/styles/Step1.style.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export default StyleSheet.create({
textAlign: 'center',
width: '80%',
},
tip: {
width: '90%',
},
images: {
alignItems: 'center',
},
Expand Down
109 changes: 90 additions & 19 deletions src/components/TxHistory/TxHistory.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// @flow

import React, {useEffect} from 'react'
import React, {useEffect, useState} from 'react'
import {connect} from 'react-redux'
import {compose} from 'redux'
import {withStateHandlers} from 'recompose'
import {useNavigationState} from '@react-navigation/native'
import {View, RefreshControl, ScrollView, Image} from 'react-native'
import SafeAreaView from 'react-native-safe-area-view'
Expand All @@ -28,6 +27,7 @@ import {
} from '../../selectors'
import TxHistoryList from './TxHistoryList'
import walletManager from '../../crypto/walletManager'
import {MultiToken} from '../../crypto/MultiToken'
import {updateHistory} from '../../actions/history'
import {checkForFlawedWallets} from '../../actions'
import {
Expand All @@ -36,19 +36,20 @@ import {
withNavigationTitle,
} from '../../utils/renderUtils'
import FlawedWalletModal from './FlawedWalletModal'
import StandardModal from '../Common/StandardModal'
import {WALLET_ROOT_ROUTES, CATALYST_ROUTES} from '../../RoutesList'
import {isByron} from '../../config/config'
import {CONFIG, isByron, isHaskellShelley} from '../../config/config'

import {formatTokenWithText} from '../../utils/format'
import image from '../../assets/img/no_transactions.png'
import globalMessages from '../../i18n/global-messages'
import globalMessages, {confirmationMessages} from '../../i18n/global-messages'

import styles from './styles/TxHistory.style'

import type {ComponentType} from 'react'
import type {Navigation} from '../../types/navigation'
import type {State} from '../../state'
import type {Token} from '../../types/HistoryTransaction'
import type {TransactionInfo, Token} from '../../types/HistoryTransaction'

const messages = defineMessages({
noTransactions: {
Expand All @@ -69,6 +70,19 @@ const warningBannerMessages = defineMessages({
},
})

const isRegistrationOpen = (() => {
const now = new Date()
const rounds = CONFIG.CATALYST.VOTING_ROUNDS
for (const round of rounds) {
const startDate = new Date(Date.parse(round.START_DATE))
const endDate = new Date(Date.parse(round.END_DATE))
if (now >= startDate && now <= endDate) {
return true
}
}
return false
})()

const NoTxHistory = injectIntl(({intl}) => (
<View style={styles.empty}>
<Image source={image} />
Expand Down Expand Up @@ -106,6 +120,19 @@ const AvailableAmountBanner = injectIntl(
),
)

type Props = {|
transactionsInfo: TransactionInfo,
navigation: Navigation,
isSyncing: boolean,
isOnline: boolean,
updateHistory: () => Promise<void>,
lastSyncError: any,
tokenBalance: MultiToken,
availableAssets: Dict<Token>,
isFlawedWallet: boolean,
walletMeta: ReturnType<typeof walletMetaSelector>,
intl: any,
|}
const TxHistory = ({
transactionsInfo,
navigation,
Expand All @@ -116,13 +143,28 @@ const TxHistory = ({
tokenBalance,
availableAssets,
isFlawedWallet,
showWarning,
setShowWarning,
walletMeta,
intl,
}) => {
}: Props) => {
const [showWarning, setShowWarning] = useState<boolean>(
isByron(walletMeta.walletImplementationId),
)

const [showInsufficientFundsModal, setShowInsufficientFundsModal] = useState<
boolean,
>(false)

const routes = useNavigationState((state) => state.routes)

const showCatalystVotingBanner =
(!walletMeta.isHW &&
isRegistrationOpen &&
isHaskellShelley(walletMeta.walletImplementationId)) ||
__DEV__

const assetMetaData = availableAssets[tokenBalance.getDefaultId()]

// TODO: move this to dashboard once it's set as default screen
useEffect(
() =>
navigation.addListener('beforeRemove', (e) => {
Expand All @@ -138,9 +180,17 @@ const TxHistory = ({
<SafeAreaView style={styles.scrollView}>
<StatusBar type="dark" />
<View style={styles.container}>
<VotingBanner
onPress={() => navigation.navigate(CATALYST_ROUTES.ROOT)}
/>
{showCatalystVotingBanner && (
<VotingBanner
onPress={() => {
if (tokenBalance.getDefault().lt(CONFIG.CATALYST.MIN_ADA)) {
setShowInsufficientFundsModal(true)
return
}
navigation.navigate(CATALYST_ROUTES.ROOT)
}}
/>
)}
{isFlawedWallet === true && (
<FlawedWalletModal
visible={isFlawedWallet === true}
Expand Down Expand Up @@ -199,6 +249,35 @@ const TxHistory = ({
)
/* eslint-enable indent */
}

<StandardModal
visible={showInsufficientFundsModal}
title={intl.formatMessage(globalMessages.attention)}
children={
<View>
<Text>
{intl.formatMessage(globalMessages.insufficientBalance, {
requiredBalance: formatTokenWithText(
CONFIG.CATALYST.MIN_ADA,
assetMetaData,
),
currentBalance: formatTokenWithText(
tokenBalance.getDefault(),
assetMetaData,
),
})}
</Text>
</View>
}
onRequestClose={() => setShowInsufficientFundsModal(false)}
primaryButton={{
label: intl.formatMessage(
confirmationMessages.commonButtons.backButton,
),
onPress: () => setShowInsufficientFundsModal(false),
}}
showCloseIcon
/>
</View>
</SafeAreaView>
)
Expand Down Expand Up @@ -233,14 +312,6 @@ export default injectIntl(
checkForFlawedWallets()
updateHistory()
}),
withStateHandlers(
{
showWarning: true,
},
{
setShowWarning: () => (showWarning: boolean) => ({showWarning}),
},
),
withNavigationTitle(({walletMeta}) => walletMeta.name),
)(TxHistory): ComponentType<ExternalProps>),
)
12 changes: 12 additions & 0 deletions src/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@ const HARDWARE_WALLETS = {
},
}

const CATALYST = {
MIN_ADA: NUMBERS.LOVELACES_PER_ADA.times(450),
VOTING_ROUNDS: [
{
NEXT_ROUND: 4,
START_DATE: '6 May 2021 19:00:00 GMT',
END_DATE: '13 May 2021 19:00:00 GMT',
},
],
}

export const CONFIG = {
DEBUG: {
// WARNING: NEVER change these flags
Expand Down Expand Up @@ -156,6 +167,7 @@ export const CONFIG = {
},
PRIMARY_ASSET_CONSTANTS,
HARDWARE_WALLETS,
CATALYST,
PIN_LENGTH: 6,
APP_LOCK_TIMEOUT: 120 * 1000,
LOG_LEVEL: _LOG_LEVEL,
Expand Down
7 changes: 7 additions & 0 deletions src/i18n/global-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,4 +552,11 @@ export default defineMessages({
id: 'components.catalyst.title',
defaultMessage: '!!!Register to vote',
},
insufficientBalance: {
id: 'components.catalyst.insufficientBalance',
defaultMessage:
'!!!Participating requires at least {requiredBalance},' +
'but you only have {currentBalance}. Unwithdrawn rewards are ' +
'not included in this amount',
},
})
9 changes: 6 additions & 3 deletions src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,10 @@
"components.walletselection.walletselectionscreen.addWalletOnShelleyButton": "Add wallet (Jormungandr ITN)",
"components.walletselection.walletselectionscreen.header": "My wallets",
"components.walletselection.walletselectionscreen.stakeDashboardButton": "Stake Dashboard",
"components.catalyst.title": "Register to vote",
"components.catalyst.banner.name": "Catalyst Voting",
"components.catalyst.insufficientBalance": "Participating requires at least {requiredBalance}, but you only have {currentBalance}. Unwithdrawn rewards are not included in this amount",
"components.catalyst.step1.subTitle": "Before you begin, make sure to download the Catalyst Voting App.",
"components.catalyst.step1.tip": "Tip: Make sure you know how to take a screenshot with your device, so that you can backup your catalyst QR code.",
"components.catalyst.step2.subTitle": "Write Down PIN",
"components.catalyst.step2.description": "Please write down this PIN as you will need it every time you want to access the Catalyst Voting app",
"components.catalyst.step3.subTitle": "Enter PIN",
Expand All @@ -350,12 +352,13 @@
"components.catalyst.step4.description": "Enter your spending password to be able to generate the required certificate for voting",
"components.catalyst.step4.subTitle": "Enter Spending Password",
"components.catalyst.step5.subTitle": "Confirm Registration",
"components.catalyst.step5.description": "Enter the spending password to confirm voting registration and submit the certificate generated in previous step to blockchain",
"components.catalyst.step5.bioAuthDescription": "Please confirm your voting registration. You will be asked to authenticate once again to sign and submit the certificate generated in the previous step.",
"components.catalyst.step5.description": "Enter your spending password to confirm your voting registration and submit the certificate generated in previous step to the blockchain.",
"components.catalyst.step6.subTitle": "Backup Catalyst Code",
"components.catalyst.step6.description": "Backup this QR code or catalyst secret code. This will be required to use the catalyst App.",
"components.catalyst.step6.note": "Keep it — you won’t be able to access this code after tapping on Complete.",
"components.catalyst.step6.secretCode": "Secret Code",
"components.catalyst.banner.name": "Catalyst Voting",
"components.catalyst.title": "Register to vote",
"crypto.errors.rewardAddressEmpty": "Reward address is empty.",
"crypto.keystore.approveTransaction": "Authorize with your biometrics",
"crypto.keystore.cancelButton": "Cancel",
Expand Down

0 comments on commit 2177abe

Please sign in to comment.