-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(management): added ability to import accounts from pevious versi…
…on (#1186) * feat(management): added ability to import accounts from pevious version * chore(wallet): rename * chore(app): fix import * chore(app): cleanup * chore(app): small fixes * chore(management): pr comments + prop validation fix * chore(app): change hover color
- Loading branch information
Maurice Dalderup
authored
Oct 13, 2019
1 parent
c862796
commit c3a6eb7
Showing
18 changed files
with
306 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,10 @@ | |
cursor: pointer; | ||
user-select: none; | ||
color: $brand; | ||
|
||
&:hover { | ||
color: $brand-dark; | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
src/renderer/account/components/Portfolio/TransactionsPanel/HorizontalIconTab/IconTab.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
.iconTab { | ||
display: flex; | ||
flex-direction: row; | ||
// align-items: flex-start; | ||
justify-content: flex-start; | ||
|
||
.icon { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createActions } from 'spunky'; | ||
|
||
import { getStorage } from 'shared/lib/storage'; | ||
|
||
export const ID = 'profiles_v1'; | ||
|
||
// Getters | ||
export default createActions(ID, () => async () => { | ||
return getStorage(ID); | ||
}); |
111 changes: 111 additions & 0 deletions
111
src/renderer/shared/components/NewWallet/Import/ExistingImport/ExistingImport.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import React from 'react'; | ||
import { string, func, shape, arrayOf } from 'prop-types'; | ||
import { map, isEmpty } from 'lodash'; | ||
import { wallet } from '@cityofzion/neon-js'; | ||
|
||
import LabeledInput from 'shared/components/Forms/LabeledInput'; | ||
import LabeledSelect from 'shared/components/Forms/LabeledSelect'; | ||
import { NEO } from 'shared/values/coins'; | ||
import accountShape from 'auth/shapes/accountShape'; | ||
|
||
const legacyAccountShape = shape({ | ||
walletName: string.isRequired, | ||
encryptedKey: string.isRequired | ||
}); | ||
|
||
export default class ExistingImport extends React.PureComponent { | ||
static propTypes = { | ||
className: string, | ||
account: accountShape.isRequired, | ||
passphrase: string.isRequired, | ||
setPassphrase: func.isRequired, | ||
addAccount: func.isRequired, | ||
accounts: arrayOf(legacyAccountShape).isRequired, | ||
setCurrentAccount: func.isRequired, | ||
currentAccount: string.isRequired, | ||
showErrorToast: func.isRequired | ||
}; | ||
|
||
static defaultProps = { | ||
className: null | ||
}; | ||
|
||
render() { | ||
const { className, accounts, passphrase, currentAccount } = this.props; | ||
|
||
return ( | ||
<form className={className} onSubmit={this.submit} id="walletForm"> | ||
<LabeledSelect | ||
id="profiel" | ||
label="Account" | ||
disabled={isEmpty(accounts)} | ||
value={currentAccount} | ||
items={this.getProfiles()} | ||
onChange={this.handleChangeCurrentAccount} | ||
/> | ||
|
||
<LabeledInput | ||
id="passphrase" | ||
type="password" | ||
label="Legacy Passphrase" | ||
placeholder="Enter your legacy passphrase" | ||
value={passphrase} | ||
onChange={this.handleChangePassphrase} | ||
/> | ||
</form> | ||
); | ||
} | ||
|
||
handleChangePassphrase = (event) => { | ||
this.props.setPassphrase(event.target.value); | ||
}; | ||
|
||
handleChangeCurrentAccount = (value) => { | ||
this.props.setCurrentAccount(value); | ||
}; | ||
|
||
submit = async () => { | ||
const { | ||
account, | ||
passphrase, | ||
accounts, | ||
setPassphrase, | ||
addAccount, | ||
showErrorToast, | ||
currentAccount | ||
} = this.props; | ||
|
||
const walletLabel = accounts.filter((acc) => acc.encryptedKey === currentAccount)[0].walletName; | ||
|
||
try { | ||
const wif = await wallet.decryptAsync(currentAccount, passphrase); | ||
const { privateKey } = new wallet.Account(wif); | ||
|
||
const options = { | ||
walletLabel, | ||
coinType: NEO, | ||
isHardware: account.isHardware, | ||
isImport: true, | ||
privateKey | ||
}; | ||
|
||
addAccount({ account, passphrase, options }); | ||
setPassphrase(''); | ||
} catch (e) { | ||
showErrorToast(`Wrong passphrase for account ${walletLabel}`); | ||
} | ||
}; | ||
|
||
getProfiles = () => { | ||
const { accounts } = this.props; | ||
|
||
if (isEmpty(accounts)) { | ||
return [{ label: 'No accounts Found', value: '' }]; | ||
} | ||
|
||
return map(accounts, ({ walletName, encryptedKey }) => ({ | ||
label: walletName, | ||
value: encryptedKey | ||
})); | ||
}; | ||
} |
31 changes: 31 additions & 0 deletions
31
src/renderer/shared/components/NewWallet/Import/ExistingImport/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { compose, withState } from 'recompose'; | ||
import { progressValues, withActions } from 'spunky'; | ||
|
||
import { withErrorToast } from 'shared/hocs/withToast'; | ||
import withProgressChange from 'shared/hocs/withProgressChange'; | ||
import { importWalletActions } from 'auth/actions/walletActions'; | ||
|
||
import ExistingImport from './ExistingImport'; | ||
|
||
const { FAILED, LOADED } = progressValues; | ||
|
||
const mapAddAccountActionsToProps = (actions) => ({ | ||
addAccount: (data) => actions.call(data) | ||
}); | ||
|
||
export default compose( | ||
withActions(importWalletActions, mapAddAccountActionsToProps), | ||
|
||
withState('currentAccount', 'setCurrentAccount', ({ accounts }) => { | ||
return accounts[0] && accounts[0].encryptedKey; | ||
}), | ||
withState('passphrase', 'setPassphrase', ''), | ||
|
||
withErrorToast(), | ||
withProgressChange(importWalletActions, FAILED, (state, props) => { | ||
props.showErrorToast(state.error); | ||
}), | ||
withProgressChange(importWalletActions, LOADED, (state, props) => { | ||
props.onConfirm(); | ||
}) | ||
)(ExistingImport); |
79 changes: 79 additions & 0 deletions
79
src/renderer/shared/components/NewWallet/Import/Import/Import.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React from 'react'; | ||
import { string, func, bool, arrayOf } from 'prop-types'; | ||
import classNames from 'classnames'; | ||
|
||
import Button from 'shared/components/Forms/Button'; | ||
import PrimaryButton from 'shared/components/Forms/PrimaryButton'; | ||
import Pill from 'shared/components/Pill'; | ||
import accountShape from 'auth/shapes/accountShape'; | ||
|
||
import ExistingImport from '../ExistingImport'; | ||
import NewImport from '../NewImport'; | ||
|
||
import styles from './Import.scss'; | ||
|
||
export default class Import extends React.PureComponent { | ||
static propTypes = { | ||
className: string, | ||
account: accountShape.isRequired, | ||
accounts: arrayOf(accountShape), | ||
onCancel: func.isRequired, | ||
onConfirm: func.isRequired, | ||
newImport: bool.isRequired, | ||
setNewImport: func.isRequired | ||
}; | ||
|
||
static defaultProps = { | ||
className: null, | ||
accounts: [] | ||
}; | ||
|
||
render() { | ||
const { className, account, accounts, newImport } = this.props; | ||
const { secretWord } = account; | ||
|
||
return ( | ||
<div className={classNames(className, styles.mnemonic)}> | ||
<Pill>{secretWord}</Pill> | ||
{this.renderForm()} | ||
{this.renderImportView({ accounts, newImport })} | ||
{this.renderActions()} | ||
</div> | ||
); | ||
} | ||
|
||
renderForm = () => { | ||
const { newImport, accounts, account, onConfirm } = this.props; | ||
|
||
return newImport ? ( | ||
<NewImport account={account} onConfirm={onConfirm} /> | ||
) : ( | ||
<ExistingImport account={account} accounts={accounts} onConfirm={onConfirm} /> | ||
); | ||
}; | ||
|
||
renderImportView = ({ accounts, newImport }) => ( | ||
<React.Fragment> | ||
{accounts && ( | ||
<div className={styles.toggle} role="button" tabIndex={0} onClick={this.handleToggle}> | ||
{newImport ? 'Import Legacy Wallet' : 'Import New Wallet'} | ||
</div> | ||
)} | ||
</React.Fragment> | ||
); | ||
|
||
renderActions = () => ( | ||
<div className={styles.actions}> | ||
<Button className={styles.action} onClick={this.props.onCancel}> | ||
Cancel | ||
</Button> | ||
<PrimaryButton className={styles.action} type="submit" form="walletForm"> | ||
Import Wallet | ||
</PrimaryButton> | ||
</div> | ||
); | ||
|
||
handleToggle = () => { | ||
this.props.setNewImport(!this.props.newImport); | ||
}; | ||
} |
27 changes: 27 additions & 0 deletions
27
src/renderer/shared/components/NewWallet/Import/Import/Import.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.mnemonic { | ||
.actions { | ||
flex: 0 0 auto; | ||
margin: 1.5rem 0 0; | ||
|
||
.action { | ||
margin-right: 10px; | ||
|
||
&:last-child { | ||
margin-right: 0; | ||
} | ||
} | ||
} | ||
|
||
.toggle { | ||
text-align: end; | ||
margin-top: -15px; | ||
font-size: 12px; | ||
color: $brand; | ||
cursor: pointer; | ||
user-select: none; | ||
|
||
&:hover { | ||
color: $brand-dark; | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/renderer/shared/components/NewWallet/Import/Import/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { compose, withState } from 'recompose'; | ||
import { withData } from 'spunky'; | ||
|
||
import withInitialCall from 'shared/hocs/withInitialCall'; | ||
import accountActions from 'auth/actions/v5AccountsActions'; | ||
|
||
import Import from './Import'; | ||
|
||
const mapAccountActionsDataToProps = (accounts) => ({ | ||
accounts: accounts && accounts.profiles | ||
}); | ||
|
||
export default compose( | ||
withInitialCall(accountActions), | ||
withData(accountActions, mapAccountActionsDataToProps), | ||
|
||
withState('newImport', 'setNewImport', true) | ||
)(Import); |
Oops, something went wrong.