Skip to content

Commit

Permalink
add support for 24 word wallets (#1014)
Browse files Browse the repository at this point in the history
* poc

add expandable component

UI feedback

remaining work

* bug fixes

* remove chimericAccountAddr and add rewardAddressHex in wallet classes and state. Rationale:
Having the reward address in redux's state was necessary for tx history UI logic (in particular, to know if deregistration tx concerns the current wallet). Note: chimericAccountAddr was used during the ITN era but is not used anywhere now. Replaced by rewardAddressHex because it's more ituitive.

* flow fix

* rename DAEDALUS_HASKELL_SHELLEY by HASKELL_SHELLEY_24, plus other minor changes

* use generic intl description message for non-15-word wallets

* add utility function to derive reward address

* (missing in previous commit)

* refactor processTxHistoryData to match logic in yoroi extension. Use fee from backend when available

* keep fees negative in UI

* use account index from config and update jest snapshot of tx history
  • Loading branch information
v-almonacid authored Oct 16, 2020
1 parent 924a6c1 commit a40ac5e
Show file tree
Hide file tree
Showing 37 changed files with 486 additions and 183 deletions.
2 changes: 2 additions & 0 deletions src/actions/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const mirrorTxHistory = () => (dispatch: Dispatch<any>) => {
transactions,
internalAddresses,
externalAddresses,
rewardAddressHex,
confirmationCounts,
isUsedAddressIndex,
numReceiveAddresses,
Expand All @@ -93,6 +94,7 @@ export const mirrorTxHistory = () => (dispatch: Dispatch<any>) => {
transactions,
internalAddresses,
externalAddresses,
rewardAddressHex,
confirmationCounts,
isUsedAddressIndex,
numReceiveAddresses,
Expand Down
2 changes: 2 additions & 0 deletions src/api/byron/__snapshots__/api.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Object {
"blockNum": Any<Number>,
"certificates": Array [],
"epoch": 87,
"fee": "169884",
"id": "2401257195a3cd7d43e832b2d2e8215828ebbcdea472ef81f8de3314a535813e",
"inputs": Array [
Object {
Expand All @@ -28,6 +29,7 @@ Object {
"status": "Successful",
"submittedAt": Any<String>,
"txOrdinal": 0,
"type": "shelley",
"withdrawals": Array [],
}
`;
2 changes: 2 additions & 0 deletions src/api/byron/facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ export const checkAndFacadeTransactionAsync = async (

return {
id: tx.hash,
type: tx.type,
fee: tx.fee ?? undefined,
status: checkAndFacadeStatus(tx.tx_state),
inputs: tx.inputs.map((i) => ({
address: i.address,
Expand Down
36 changes: 31 additions & 5 deletions src/api/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,38 @@ export type RemoteTxBlockMeta = {|
+slot: number,
|}

export type RemoteCertificateMeta = {
kind: CertificateKind,
rewardAddress?: string, // hex
poolKeyHash?: string, // hex
}
// See complete types in:
// https://github.com/Emurgo/yoroi-graphql-migration-backend#output-6
export type RemoteCertificateMeta =
| {|
kind: typeof CERTIFICATE_KIND.STAKE_REGISTRATION,
rewardAddress: string, // hex
|}
| {|
kind: typeof CERTIFICATE_KIND.STAKE_DEREGISTRATION,
rewardAddress: string, // hex
|}
| {|
kind: typeof CERTIFICATE_KIND.STAKE_DELEGATION,
rewardAddress: string, // hex
poolKeyHash: string, // hex
|}
| {|
kind: typeof CERTIFICATE_KIND.POOL_REGISTRATION,
poolParams: Object, // we don't care about this for now
|}
| {|
kind: typeof CERTIFICATE_KIND.POOL_RETIREMENT,
poolKeyHash: string, // hex
|}
| {|
kind: typeof CERTIFICATE_KIND.MOVE_INSTANTANEOUS_REWARDS,
rewards: {[addresses: string]: string},
pot: 0 | 1,
|}
export type RemoteTxInfo = {|
+type: 'byron' | 'shelley',
+fee?: string, // only in shelley txs
+hash: string,
+last_update: string, // timestamp with timezone
+tx_state: TransactionStatus,
Expand Down
Binary file added src/assets/img/chevron_down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/chevron_down@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/chevron_down@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/chevron_up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/chevron_up@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/chevron_up@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions src/components/Common/ExpandableItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// @flow
import React from 'react'
import {compose} from 'redux'
import {withStateHandlers} from 'recompose'
import {TouchableOpacity, View, Image} from 'react-native'

import {Text} from '../UiKit'
import chevronDown from '../../assets/img/chevron_down.png'
import chevronUp from '../../assets/img/chevron_up.png'

import styles from './styles/ExpandableItem.style'

import type {ComponentType} from 'react'

type Props = {
label: string,
content: string,
disabled?: boolean,
onPress: () => void,
expanded: boolean,
style?: Object,
}

export const ExpandableItem = ({
label,
content,
disabled,
onPress,
expanded,
style,
}: Props) => (
<TouchableOpacity onPress={onPress} activeOpacity={0.5}>
<View style={style}>
<View style={styles.labelWrapper}>
<Text secondary style={[disabled === true && styles.disabled]}>
{label}
</Text>
<Image
style={styles.icon}
source={expanded ? chevronUp : chevronDown}
/>
</View>
{expanded && (
<View style={styles.contentWrapper}>
<Text>{content}</Text>
</View>
)}
</View>
</TouchableOpacity>
)

type ExternalProps = {
label: string,
content: string,
disabled?: boolean,
style?: Object,
}

export default (compose(
withStateHandlers(
{
expanded: false,
},
{
onPress: (state) => () => ({expanded: !state.expanded}),
},
),
)(ExpandableItem): ComponentType<ExternalProps>)
22 changes: 22 additions & 0 deletions src/components/Common/styles/ExpandableItem.style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @flow
import {StyleSheet} from 'react-native'

import {COLORS} from '../../../styles/config'

export default StyleSheet.create({
labelWrapper: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
padding: 12,
},
icon: {
marginLeft: 5,
},
disabled: {
color: COLORS.DISABLED,
},
contentWrapper: {
padding: 16,
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import _ from 'lodash'

import {Text, Button, ValidatedTextInput, StatusBar} from '../../UiKit'
import {WALLET_INIT_ROUTES} from '../../../RoutesList'
import {CONFIG} from '../../../config/config'
import {CONFIG, getWalletConfigById} from '../../../config/config'
import {
validateRecoveryPhrase,
INVALID_PHRASE_ERROR_CODES,
Expand All @@ -25,6 +25,7 @@ import styles from './styles/RestoreWalletScreen.style'
import type {InvalidPhraseError} from '../../../utils/validators'
import type {ComponentType} from 'react'
import type {Navigation} from '../../../types/navigation'
import type {WalletImplementationId} from '../../../config/types'

const mnemonicInputErrorsMessages = defineMessages({
TOO_LONG: {
Expand Down Expand Up @@ -112,7 +113,11 @@ const RestoreWalletScreen = ({
isKeyboardOpen,
navigation,
}) => {
const errors = validateRecoveryPhrase(phrase)
const implId: WalletImplementationId = navigation.getParam(
'walletImplementationId',
)
const walletConfig = getWalletConfigById(implId)
const errors = validateRecoveryPhrase(phrase, walletConfig.MNEMONIC_LEN)
const visibleErrors = isKeyboardOpen
? errorsVisibleWhileWriting(errors.invalidPhrase || [])
: errors.invalidPhrase || []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const _getPlate = async (
) => {
switch (walletImplId) {
case WALLET_IMPLEMENTATION_REGISTRY.HASKELL_SHELLEY:
case WALLET_IMPLEMENTATION_REGISTRY.HASKELL_SHELLEY_24:
return await generateShelleyPlateFromMnemonics(phrase, count)
case WALLET_IMPLEMENTATION_REGISTRY.HASKELL_BYRON:
return generateByronPlateFromMnemonics(phrase, count)
Expand Down
22 changes: 10 additions & 12 deletions src/components/WalletInit/WalletFreshInitScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ import {Button, StatusBar, ScreenBackground} from '../UiKit'
import styles from './styles/WalletInitScreen.style'
import {WALLET_INIT_ROUTES} from '../../RoutesList'
import {walletIsInitializedSelector} from '../../selectors'
import {
NETWORK_REGISTRY,
WALLET_IMPLEMENTATION_REGISTRY,
} from '../../config/types'
import {NETWORKS} from '../../config/networks'
import {CONFIG} from '../../config/config'

import type {State} from '../../state'
import type {Navigation} from '../../types/navigation'
Expand Down Expand Up @@ -59,10 +55,12 @@ const WalletInitScreen = ({
</View>
<Button
onPress={(event) =>
// assume regular haskell shelley wallet. In next screen, user
// may choose to use a 24-word mnemonic (-> diffferent impl id)
navigateInitWallet(
event,
NETWORK_REGISTRY.HASKELL_SHELLEY,
WALLET_IMPLEMENTATION_REGISTRY.HASKELL_SHELLEY,
CONFIG.NETWORKS.HASKELL_SHELLEY.NETWORK_ID,
CONFIG.WALLETS.HASKELL_SHELLEY.WALLET_IMPLEMENTATION_ID,
)
}
title={`${intl.formatMessage(
Expand All @@ -76,8 +74,8 @@ const WalletInitScreen = ({
onPress={(event) =>
navigateInitWallet(
event,
NETWORK_REGISTRY.HASKELL_SHELLEY,
WALLET_IMPLEMENTATION_REGISTRY.HASKELL_BYRON,
CONFIG.NETWORKS.HASKELL_SHELLEY.NETWORK_ID,
CONFIG.WALLETS.HASKELL_BYRON.WALLET_IMPLEMENTATION_ID,
)
}
title={`${intl.formatMessage(
Expand All @@ -88,14 +86,14 @@ const WalletInitScreen = ({
testID="addWalletOnByronButton"
/>

{NETWORKS.JORMUNGANDR.ENABLED && (
{CONFIG.NETWORKS.JORMUNGANDR.ENABLED && (
<Button
outline
onPress={(event) =>
navigateInitWallet(
event,
NETWORK_REGISTRY.JORMUNGANDR,
WALLET_IMPLEMENTATION_REGISTRY.JORMUNGANDR_ITN,
CONFIG.NETWORKS.JORMUNGANDR.NETWORK_ID,
CONFIG.WALLETS.JORMUNGANDR_ITN.WALLET_IMPLEMENTATION_ID,
)
}
title={intl.formatMessage(messages.addWalletOnShelleyButton)}
Expand Down
Loading

0 comments on commit a40ac5e

Please sign in to comment.