Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
06b76d9
Corrections by code review
dmernies-iohk Dec 4, 2019
a547967
decrypt utils are added to save encrypted spending password and data
dmernies-iohk Dec 11, 2019
d76a264
Create spending password screen is added and displayed when password …
dmernies-iohk Dec 11, 2019
17ab19a
RestoreWalletFromPrivateKey component is created to improve visual co…
dmernies-iohk Dec 12, 2019
e42bc53
A new component to revoer BIP39 phrases is added
dmernies-iohk Dec 12, 2019
decedd5
Saving encrypted wallet function is added and ivoked with hardcoded p…
dmernies-iohk Dec 13, 2019
b94f937
speding password input on restore key is added
dmernies-iohk Dec 16, 2019
689b791
Unlock wallet screen is added to unlock with spending password
dmernies-iohk Dec 18, 2019
892d543
Unlocking wallet function are renamed
dmernies-iohk Dec 18, 2019
5c020db
Cleaning unused code from routes and nodeConection
dmerniestic1987 Dec 19, 2019
0112de9
Corrections by code review
dmerniestic1987 Jan 2, 2020
53d6a6f
Hash is removed from the key that is saved from in localStorate. Now …
dmernies-iohk Jan 7, 2020
8c9a28f
UnlockWalletPassword is used instead of SpendingPassword
dmernies-iohk Jan 8, 2020
f4e53a9
fake salt is removed
dmernies-iohk Jan 8, 2020
797fabb
walletId is removed
dmernies-iohk Jan 10, 2020
9815315
Code Review improvements
dmernies-iohk Jan 10, 2020
4cecbb8
UnlockWalletPassword is mandatory now
dmernies-iohk Jan 14, 2020
853a5e8
A new component to create a new unlock wallet is added
dmernies-iohk Jan 15, 2020
0342b9e
Hide spending password error is deleted
dmernies-iohk Jan 16, 2020
ecc2841
corrections by code review
dmernies-iohk Jan 16, 2020
75a13f1
Form.Control.Feeback is added instead of instead of artisan validations
dmernies-iohk Jan 16, 2020
1761414
<span> tag is used insetead of <em> and Form.Feedback is added
dmernies-iohk Jan 17, 2020
86215c3
Validation of private key is added
dmernies-iohk Jan 17, 2020
86d49cc
Corrections by code review
dmernies-iohk Jan 17, 2020
3c874e6
New component to create a valid unlock password is added
dmernies-iohk Jan 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/explorer/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"rules": {
"func-names": "error",
"new-cap": "off",
"new-cap": ["off", { "capIsNewExceptionPattern": "^Aesjs\.." }],
"arrow-parens": "off",
"consistent-return": "off",
"comma-dangle": "off",
Expand Down
11 changes: 10 additions & 1 deletion examples/wallet/app/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import Settings from './pages/Settings';
import ChooseRestoreOrImport from './containers/ChooseRestoreOrImport';
import Delegate from './pages/Delegate';
import Index from './containers/Index';
import InputKeys from './containers/InputKeys';
import InputKeys from './pages/InputKeys';
import UnlockWallet from './containers/UnlockWallet';
import CreateWallet from './containers/CreateWallet';
import CreateWalletRevealMnemonic from './containers/CreateWalletRevealMnemonic';

export default () => (
<App>
Expand All @@ -19,6 +22,12 @@ export default () => (
<Route path={routes.STAKING} component={Delegate} />
<Route path={routes.SETTINGS} component={Settings} />
<Route path={routes.INPUT_KEYS} component={InputKeys} />
<Route path={routes.UNLOCK_WALLET} component={UnlockWallet} />
<Route path={routes.CREATE_WALLET_KEYS} component={CreateWallet} />
<Route
path={routes.REVEAL_MNEMONIC_PHRASE}
component={CreateWalletRevealMnemonic}
/>
<Route
path={routes.CHOOSE_RESTORE_OR_IMPORT}
component={ChooseRestoreOrImport}
Expand Down
85 changes: 41 additions & 44 deletions examples/wallet/app/actions/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,38 @@ import {
getTransactions
} from '../utils/nodeConnection';
import { isValidMnemonic, createSeedFromMnemonic } from '../utils/mnemonic';
import { saveAccountInfoInLocalStorage } from '../utils/storage';
import {
saveEncryptedAccountInfo,
readEncryptedAccountInfo
} from '../utils/storage';

import routes from '../constants/routes.json';

export type SetKeysAction = { type: 'SET_KEYS' } & AccountKeys;
export const SET_KEYS = 'SET_KEYS';
export const PRIVATE_KEY_ERROR = 'privateKeyError';
export const ACCOUNT_STATE_ERROR = 'accountStateError';

export function setAccount(privateKey: string): Thunk {
export function setAccount(
privateKey: string,
unlockWalletPassword: string
): Thunk<SetKeysAction> {
return function setAccountThunk(dispatch) {
return getAccountFromPrivateKey(privateKey).then(
curry(initializeKeysAndRedirect)(dispatch)
return getAccountFromPrivateKey(privateKey).then(keys =>
curry(initializeKeysAndRedirect)(dispatch, keys, unlockWalletPassword)
);
};
}

export function setAccountFromPrivateKey(privateKey: string): Thunk {
return function setAccountFromPrivateKeyThunk(dispatch) {
getAccountFromPrivateKey(privateKey)
.then(loadedPrivateKey => {
dispatch({
type: SET_KEYS,
...loadedPrivateKey
});
return dispatch(updateAccountTransactionsAndState());
})
.catch(error => {
console.error(error);
throw new Error(PRIVATE_KEY_ERROR);
});
};
}

export function updateAccountTransactionsAndState(): Thunk {
return function updateAccountTransactionsAndStateThunk(dispatch) {
return Promise.all([
dispatch(updateAccountTransactions()),
dispatch(updateNodeSettings()),
dispatch(updateAccountState())
]).then(() => dispatch(push(routes.WALLET)));
export function setKeysWithUnlockWalletPassword(
unlockWalletPassword: string = ''
): Thunk<SetKeysAction> {
return function setKeysWithUnlockWalletPasswordThunk(dispatch) {
const accountKeys = readEncryptedAccountInfo(unlockWalletPassword);
if (accountKeys) {
return getAccountFromPrivateKey(accountKeys.privateKey).then(keys =>
curry(initializeKeysAndRedirect)(dispatch, keys, unlockWalletPassword)
);
}
throw new Error('Invalid password');
};
}

Expand All @@ -83,30 +74,36 @@ export function updateAccountTransactionsAndState(): Thunk {
* @param {boolean} saveAccount If true, the keys are stored in the local storage
*/
const initializeKeysAndRedirect = (
dispatch: Dispatch<SetKeysAction>,
dispatch: Dispatch,
keys: AccountKeys,
saveAccount?: boolean = true
unlockWalletPassword: string = ''
) => {
dispatch({
type: SET_KEYS,
...keys
});
if (saveAccount) {
saveAccountInfoInLocalStorage(keys);
}

return dispatch(updateAccountTransactionsAndState());
saveEncryptedAccountInfo(unlockWalletPassword, keys);

return Promise.all([
dispatch(updateAccountTransactions()),
dispatch(updateNodeSettings()),
dispatch(updateAccountState())
])
.catch(console.error)
.then(() => dispatch(push(routes.WALLET)));
};

export function setAccountFromMnemonic(
mnemonicPhrase: string,
mnemonicPassword?: string
) {
mnemonicPassword: string,
unlockWalletPassword: string
): Thunk<SetKeysAction> {
if (isValidMnemonic(mnemonicPhrase)) {
const seed = createSeedFromMnemonic(mnemonicPhrase, mnemonicPassword);
return function setAccountThunk(dispatch) {
return getAccountFromSeed(seed).then(
curry(initializeKeysAndRedirect)(dispatch)
return getAccountFromSeed(seed).then(keys =>
curry(initializeKeysAndRedirect)(dispatch, keys, unlockWalletPassword)
);
};
}
Expand All @@ -119,7 +116,7 @@ export type SetAccountStateAction = {
} & AccountState;
export const SET_ACCOUNT_STATE = 'SET_ACCOUNT_STATE';

export function updateAccountState(): Thunk {
export function updateAccountState(): Thunk<SetAccountStateAction> {
return function updateAccountStateThunk(dispatch, getState) {
const { identifier }: { identifier: Identifier } = getState().account;
if (!identifier) {
Expand All @@ -139,7 +136,7 @@ export function updateAccountState(): Thunk {
// TODO: display a notification or something
.catch(() => {
console.error('there was an error fetching account info');
return Promise.reject(new Error(ACCOUNT_STATE_ERROR));
return Promise.reject();
})
);
};
Expand All @@ -151,7 +148,7 @@ export type SetTransactionsAction = {
};
export const SET_TRANSACTIONS = 'SET_TRANSACTIONS';

export function updateAccountTransactions(): Thunk {
export function updateAccountTransactions(): Thunk<SetAccountStateAction> {
return function updateAccountTransactionsThunk(dispatch, getState) {
const { address }: { address: Address } = getState().account;
if (!address) {
Expand All @@ -171,7 +168,7 @@ export function updateAccountTransactions(): Thunk {
// TODO: display a notification or something
.catch(() => {
console.error('there was an error fetching transactions');
return Promise.reject(new Error(ACCOUNT_STATE_ERROR));
return Promise.reject();
})
);
};
Expand Down
25 changes: 4 additions & 21 deletions examples/wallet/app/actions/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,15 @@
import { push } from 'connected-react-router';
import type { Dispatch, GetState } from '../reducers/types';
import type { Address } from '../models';
import routes from '../constants/routes.json';
import {
updateAccountTransactionsAndState,
ACCOUNT_STATE_ERROR
} from './account';
import { readAccountKeysFromLocalStorage } from '../utils/storage';
import routes from '../constants/routes';

export const SET_KEYS = 'SET_KEYS';
import { isUnlockWalletPasswordCreated } from '../utils/storage';

// eslint-disable-next-line import/prefer-default-export
export const redirectToFirstAppPage = () => {
return (dispatch: Dispatch, getState: GetState) => {
const accountKeys = readAccountKeysFromLocalStorage();
if (accountKeys) {
dispatch({
type: SET_KEYS,
...accountKeys
});
return dispatch(updateAccountTransactionsAndState()).catch(error => {
if (error.message === ACCOUNT_STATE_ERROR) {
console.error('There was an error retrieving account status');
}

return dispatch(push(routes.WALLET));
});
}
if (isUnlockWalletPasswordCreated())
return dispatch(push(routes.UNLOCK_WALLET));
const {
account: { address }
}: { account: { address: Address } } = getState();
Expand Down
97 changes: 97 additions & 0 deletions examples/wallet/app/components/CreateUnlockWalletPassword.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// @flow
import React, { useState } from 'react';
import Form from 'react-bootstrap/Form';
import PropTypes from 'prop-types';

CreateUnlockWalletPassword.propTypes = {
setValidCreateUnlockWalletPassword: PropTypes.func
};
export default function CreateUnlockWalletPassword({
setValidCreateUnlockWalletPassword
}) {
const checkValidUnlockWalletPassword = function checkValidUnlockWalletPassword(
pass
) {
setIsValidPassword(true);
if (!pass) {
setIsValidPassword(false);
return false;
}
if (pass.length < 8) {
setIsValidPassword(false);
return false;
}
};

const checkValidUnlockWalletConfirmation = function checkValidUnlockWalletConfirmation(
unlockWalletPassword,
confirmation
) {
setArePasswordAndConfirmationEqual(true);
let isValidUnlockPassword = true;
if (!confirmation || confirmation.length < 8) {
isValidUnlockPassword = false;
}

if (unlockWalletPassword !== confirmation) {
setArePasswordAndConfirmationEqual(false);
isValidUnlockPassword = false;
}

setValidCreateUnlockWalletPassword(
unlockWalletPassword,
isValidUnlockPassword
);
return isValidUnlockPassword;
};

const [
arePasswordAndConfirmationEqual,
setArePasswordAndConfirmationEqual
] = useState(true);

const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [isValidPassword, setIsValidPassword] = useState(true);

return (
<Form.Group>
<Form.Label className="mt-5">Unlock wallet:</Form.Label>
<Form.Group>
<Form.Control
type="password"
id="password"
name="password"
placeholder="New password (min 8 chars)"
value={password}
isInvalid={!isValidPassword}
onChange={event => setPassword(event.target.value)}
onBlur={() => checkValidUnlockWalletPassword(password)}
/>
<Form.Control.Feedback type="invalid">
The password must have at least 8 chars.
</Form.Control.Feedback>
<Form.Control
type="password"
name="confirmPassword"
id="confirmPassword"
placeholder="Confirm password"
value={confirmPassword}
isInvalid={!arePasswordAndConfirmationEqual}
onChange={event => setConfirmPassword(event.target.value)}
onBlur={() =>
checkValidUnlockWalletConfirmation(password, confirmPassword)
}
className="mt-3"
/>
<Form.Text>
This key allows you to unlock your wallet every time you start it and
to keep your account data in a more secure way.
</Form.Text>
<Form.Control.Feedback type="invalid">
password and confirmation must be the same.
</Form.Control.Feedback>
</Form.Group>
</Form.Group>
);
}
Loading