Skip to content

Commit

Permalink
migrate save readonly wallet to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
wolverineks committed Dec 1, 2021
1 parent ff647b6 commit 3ed825d
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 125 deletions.
3 changes: 3 additions & 0 deletions legacy/config/config.d.ts
Expand Up @@ -7,6 +7,9 @@ export var isByron: (walletImplementationId: string) => boolean

// prettier-ignore
export var CONFIG: {
NUMBERS: {
HARD_DERIVATION_START: number
},
DEBUG: {
PREFILL_FORMS: boolean,
WALLET_NAME: string,
Expand Down
@@ -1,10 +1,8 @@
// @flow

import {NavigationRouteContext} from '@react-navigation/native'
import {storiesOf} from '@storybook/react-native'
import React from 'react'

import SaveReadOnlyWalletScreen from './SaveReadOnlyWalletScreen'
import {SaveReadOnlyWalletScreen} from './SaveReadOnlyWalletScreen'

storiesOf('SaveReadOnlyWalletScreen', module).add('Default', () => {
const route = {
Expand All @@ -14,6 +12,8 @@ storiesOf('SaveReadOnlyWalletScreen', module).add('Default', () => {
publicKeyHex:
'42cfdc53da2220ba52ce62f8e20ab9bb99857a3fceacf43d676d7987ad909b53ed75534e0d0ee8fce835eb2e7c67c5caec18a9c894388d9a046380edebbfc46d',
path: [2147485500, 2147485463, 2147483648],
networkId: 1,
walletImplmentationId: 'haskell-shelley',
},
}

Expand Down
@@ -1,118 +1,33 @@
// @flow

import {useNavigation, useRoute} from '@react-navigation/native'
import React, {useEffect, useState} from 'react'
import {defineMessages, useIntl} from 'react-intl'
// TODO: in the future, prefer SafeAreaView from react-native-safe-area-context,
// current version however doesn't work well on iOS
import {FlatList, SafeAreaView, ScrollView, View} from 'react-native'
import {StyleSheet} from 'react-native'
import {useDispatch} from 'react-redux'

// $FlowExpectedError
import {Icon} from '../../../../src/components'
// $FlowExpectedError
import WalletAddress from '../../../../src/WalletInit/WalletAddress'
// $FlowExpectedError
import {WalletNameForm} from '../../../../src/WalletInit/WalletNameForm'
import {createWalletWithBip44Account, handleGeneralError} from '../../../actions'
import {CONFIG} from '../../../config/config'
import type {NetworkId} from '../../../config/types'
import {generateShelleyPlateFromKey} from '../../../crypto/shelley/plate'
import {ROOT_ROUTES, WALLET_ROOT_ROUTES} from '../../../RoutesList'
import assert from '../../../utils/assert'
import {Logger} from '../../../utils/logging'
import {ignoreConcurrentAsyncHandler} from '../../../utils/utils'
import {Line, StatusBar, Text} from '../../UiKit'
import styles from './styles/SaveReadOnlyWalletScreen.style'
import {createWalletWithBip44Account, handleGeneralError} from '../../legacy/actions'
import {Line, StatusBar, Text} from '../../legacy/components/UiKit'
import {CONFIG} from '../../legacy/config/config'
import type {NetworkId} from '../../legacy/config/types'
import {generateShelleyPlateFromKey} from '../../legacy/crypto/shelley/plate'
import {ROOT_ROUTES, WALLET_ROOT_ROUTES} from '../../legacy/RoutesList'
import {WalletMeta} from '../../legacy/state'
import {theme} from '../../legacy/styles/config'
import assert from '../../legacy/utils/assert'
import {Logger} from '../../legacy/utils/logging'
import {ignoreConcurrentAsyncHandler} from '../../legacy/utils/utils'
import {Icon} from '../components'
import {useSetSelectedWallet, useSetSelectedWalletMeta} from '../SelectedWallet'
import {WalletAddress} from './WalletAddress'
import {WalletNameForm} from './WalletNameForm'

const messages = defineMessages({
defaultWalletName: {
id: 'components.walletinit.savereadonlywalletscreen.defaultWalletName',
defaultMessage: '!!!My read-only wallet',
},
checksumLabel: {
id: 'components.walletinit.verifyrestoredwallet.checksumLabel',
defaultMessage: '!!!Chacksum label',
},
walletAddressLabel: {
id: 'components.walletinit.verifyrestoredwallet.walletAddressLabel',
defaultMessage: '!!!Wallet Address(es):',
},
key: {
id: 'components.walletinit.savereadonlywalletscreen.key',
defaultMessage: '!!!Key:',
},
derivationPath: {
id: 'components.walletinit.savereadonlywalletscreen.derivationPath',
defaultMessage: '!!!Derivation path:',
},
})

const CheckSumView = ({icon, checksum}: {icon: string, checksum: string}) => (
<View style={styles.checksumView}>
<Icon.WalletAccount iconSeed={icon} />
<Text style={styles.checksumText}>{checksum}</Text>
</View>
)

type WalletInfoProps = {|
plate: {
accountPlate: {
ImagePart: string,
TextPart: string,
},
addresses: Array<string>,
},
normalizedPath: Array<number>,
publicKeyHex: string,
networkId: NetworkId,
|}

const WalletInfoView = ({plate, normalizedPath, publicKeyHex, networkId}: WalletInfoProps) => {
const intl = useIntl()

return (
<View style={styles.walletInfoContainer}>
<ScrollView style={styles.scrollView}>
<View style={styles.checksumContainer}>
<Text>{intl.formatMessage(messages.checksumLabel)}</Text>
{!!plate.accountPlate.ImagePart && (
<CheckSumView icon={plate.accountPlate.ImagePart} checksum={plate.accountPlate.TextPart} />
)}
</View>

<View style={styles.addressesContainer}>
<Text>{intl.formatMessage(messages.walletAddressLabel)}</Text>
<FlatList
data={plate.addresses}
keyExtractor={(item) => item}
renderItem={({item}) => <WalletAddress addressHash={item} networkId={networkId} />}
/>
</View>

<Line />

<View style={styles.keyAttributesContainer}>
<Text style={styles.label}>{intl.formatMessage(messages.key)}</Text>
<View style={styles.keyView}>
<Text secondary monospace numberOfLines={1} ellipsizeMode="middle">
{publicKeyHex}
</Text>
</View>

<Text style={styles.label}>{intl.formatMessage(messages.derivationPath)}</Text>
<Text secondary monospace>
{`m/${normalizedPath[0]}'/${normalizedPath[1]}'/${normalizedPath[2]}`}
</Text>
</View>
</ScrollView>
</View>
)
}

const SaveReadOnlyWalletScreen = () => {
export const SaveReadOnlyWalletScreen = () => {
const intl = useIntl()
const strings = useStrings()
const navigation = useNavigation()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const route: any = useRoute()
const [isWaiting, setIsWaiting] = React.useState(false)
const dispatch = useDispatch()
Expand Down Expand Up @@ -142,6 +57,9 @@ const SaveReadOnlyWalletScreen = () => {
}
}

const setSelectedWalletMeta = useSetSelectedWalletMeta()
const setSelectedWallet = useSetSelectedWallet()

// eslint-disable-next-line react-hooks/exhaustive-deps
const onSubmit = React.useCallback(
ignoreConcurrentAsyncHandler(
Expand All @@ -152,27 +70,44 @@ const SaveReadOnlyWalletScreen = () => {
assert.assert(networkId != null, 'networkId')
assert.assert(!!walletImplementationId, 'walletImplementationId')

withActivityIndicator(
async () =>
await dispatch(
createWalletWithBip44Account(
name,
publicKeyHex,
networkId,
walletImplementationId,
null,
true, // important: read-only flag
),
withActivityIndicator(async () => {
const wallet = await dispatch(
createWalletWithBip44Account(
name,
publicKeyHex,
networkId,
walletImplementationId,
null,
true, // important: read-only flag
),
)
)

const walletMeta: WalletMeta = {
name,

id: wallet.id,
networkId: wallet.networkId,
walletImplementationId: wallet.walletImplementationId,
isHW: wallet.isHW,
checksum: wallet.checksum,
isEasyConfirmationEnabled: wallet.isEasyConfirmationEnabled,
provider: wallet.provider,
}
setSelectedWalletMeta(walletMeta)
setSelectedWallet(wallet)
})

navigation.navigate(ROOT_ROUTES.WALLET, {
screen: WALLET_ROOT_ROUTES.MAIN_WALLET_ROUTES,
})
} catch (e) {
setIsWaiting(false)
Logger.error('SaveReadOnlyWalletScreen::onSubmit', e)
await handleGeneralError(e.message, e, intl)
if (e instanceof Error) {
await handleGeneralError(e.message, e, intl)
}

throw e
}
},
1000,
Expand All @@ -194,7 +129,7 @@ const SaveReadOnlyWalletScreen = () => {
<StatusBar type="dark" />
<WalletNameForm
onSubmit={onSubmit}
defaultWalletName={intl.formatMessage(messages.defaultWalletName)}
defaultWalletName={strings.defaultWalletName}
containerStyle={styles.walletFormStyle}
bottomContent={
<WalletInfoView
Expand All @@ -211,4 +146,152 @@ const SaveReadOnlyWalletScreen = () => {
)
}

export default SaveReadOnlyWalletScreen
const SECTION_MARGIN = 22
const LABEL_MARGIN = 6

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.COLORS.BACKGROUND,
paddingHorizontal: 16,
},
scrollView: {
paddingRight: 10,
},
walletInfoContainer: {
marginTop: SECTION_MARGIN,
},
label: {
marginBottom: LABEL_MARGIN,
},
checksumContainer: {
marginBottom: SECTION_MARGIN,
},
checksumView: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 12,
borderColor: 'red',
flexWrap: 'wrap',
},
checksumText: {
fontSize: 18,
fontWeight: 'bold',
paddingLeft: 12,
},
addressesContainer: {
marginBottom: SECTION_MARGIN,
},
keyAttributesContainer: {
marginTop: SECTION_MARGIN,
},
keyView: {
padding: 4,
backgroundColor: theme.COLORS.CODE_STYLE_BACKGROUND,
marginBottom: 10,
},
walletFormStyle: {
paddingTop: 0,
paddingHorizontal: 0,
},
walletFormButtonStyle: {
marginHorizontal: 0,
},
})

const messages = defineMessages({
defaultWalletName: {
id: 'components.walletinit.savereadonlywalletscreen.defaultWalletName',
defaultMessage: '!!!My read-only wallet',
},
checksumLabel: {
id: 'components.walletinit.verifyrestoredwallet.checksumLabel',
defaultMessage: '!!!Chacksum label',
},
walletAddressLabel: {
id: 'components.walletinit.verifyrestoredwallet.walletAddressLabel',
defaultMessage: '!!!Wallet Address(es):',
},
key: {
id: 'components.walletinit.savereadonlywalletscreen.key',
defaultMessage: '!!!Key:',
},
derivationPath: {
id: 'components.walletinit.savereadonlywalletscreen.derivationPath',
defaultMessage: '!!!Derivation path:',
},
})

const useStrings = () => {
const intl = useIntl()

return {
defaultWalletName: intl.formatMessage(messages.defaultWalletName),
checksumLabel: intl.formatMessage(messages.checksumLabel),
walletAddressLabel: intl.formatMessage(messages.walletAddressLabel),
key: intl.formatMessage(messages.key),
derivationPath: intl.formatMessage(messages.derivationPath),
}
}

const CheckSumView = ({icon, checksum}: {icon: string; checksum: string}) => (
<View style={styles.checksumView}>
<Icon.WalletAccount iconSeed={icon} />
<Text style={styles.checksumText}>{checksum}</Text>
</View>
)

type WalletInfoProps = {
plate: {
accountPlate: {
ImagePart: string
TextPart: string
}
addresses: Array<string>
}
normalizedPath: Array<number>
publicKeyHex: string
networkId: NetworkId
}

const WalletInfoView = ({plate, normalizedPath, publicKeyHex, networkId}: WalletInfoProps) => {
const strings = useStrings()

return (
<View style={styles.walletInfoContainer}>
<ScrollView style={styles.scrollView}>
<View style={styles.checksumContainer}>
<Text>{strings.checksumLabel}</Text>
{!!plate.accountPlate.ImagePart && (
<CheckSumView icon={plate.accountPlate.ImagePart} checksum={plate.accountPlate.TextPart} />
)}
</View>

<View style={styles.addressesContainer}>
<Text>{strings.walletAddressLabel}</Text>
<FlatList
data={plate.addresses}
keyExtractor={(item) => item}
renderItem={({item}) => <WalletAddress addressHash={item} networkId={networkId} />}
/>
</View>

<Line />

<View style={styles.keyAttributesContainer}>
<Text style={styles.label}>{strings.key}</Text>
<View style={styles.keyView}>
<Text secondary monospace numberOfLines={1} ellipsizeMode="middle">
{publicKeyHex}
</Text>
</View>

<Text style={styles.label}>{strings.derivationPath}</Text>
<Text secondary monospace>
{`m/${normalizedPath[0]}'/${normalizedPath[1]}'/${normalizedPath[2]}`}
</Text>
</View>
</ScrollView>
</View>
)
}

0 comments on commit 3ed825d

Please sign in to comment.