diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json
index 3b85c1e37f..eec1a0ffed 100644
--- a/i18n/locales/en/common.json
+++ b/i18n/locales/en/common.json
@@ -25,12 +25,12 @@
"Buy Lisk": "Buy Lisk",
"Cancel": "Cancel",
"Check for updates...": "Check for updates...",
- "Choose the correct phrases to confirm.": "Choose the correct phrases to confirm.",
"Close": "Close",
"Coming soon.": "Coming soon.",
"Confirm": "Confirm",
"Confirm (Fee: 1 LSK)": "Confirm (Fee: 1 LSK)",
"Confirm (Fee: {{fee}} LSK)": "Confirm (Fee: {{fee}} LSK)",
+ "Confirm to register your second passphrase on the blockchain.": "Confirm to register your second passphrase on the blockchain.",
"Confirm transfer": "Confirm transfer",
"Confirmation in the next step": "Confirmation in the next step",
"Confirmation in the next step.": "Confirmation in the next step.",
@@ -39,9 +39,11 @@
"Copied!": "Copied!",
"Copy": "Copy",
"Copy Transaction ID to clipboard": "Copy Transaction ID to clipboard",
+ "Create": "Create",
"Create Lisk ID": "Create Lisk ID",
"Create a Lisk ID to gain access to all services.": "Create a Lisk ID to gain access to all services.",
"Create your Lisk ID": "Create your Lisk ID",
+ "Create your second passphrase": "Create your second passphrase",
"Current version is up-to-date.": "Current version is up-to-date.",
"Currently we speaking english and german.": "Currently we speaking english and german.",
"Custom Node": "Custom Node",
@@ -71,10 +73,13 @@
"Fee: {{fee}} LSK": "Fee: {{fee}} LSK",
"Final confirmation": "Final confirmation",
"Get to your Dashboard": "Get to your Dashboard",
+ "Go back to Dashboard": "Go back to Dashboard",
"Got it": "Got it",
+ "Great!\nYou’re almost finished": "Great!\nYou’re almost finished",
"Help": "Help",
"Hide passphrase": "Hide passphrase",
"I am responsible for keeping my passphrase safe. No one can reset it, not even Lisk.": "I am responsible for keeping my passphrase safe. No one can reset it, not even Lisk.",
+ "I confirm (Fee: 5 LSK)": "I confirm (Fee: 5 LSK)",
"I understand": "I understand",
"In": "In",
"Incoming": "Incoming",
@@ -103,7 +108,6 @@
"Lock ID": "Lock ID",
"Lock ID’s automatically after 10 minutes.": "Lock ID’s automatically after 10 minutes.",
"Log in": "Log in",
- "Losing access to this passphrase will mean no funds can be sent from this account.": "Losing access to this passphrase will mean no funds can be sent from this account.",
"Main menu": "Main menu",
"Mainnet": "Mainnet",
"Maximum of 101 votes in total": "Maximum of 101 votes in total",
@@ -137,6 +141,7 @@
"Please click Next, then move around your mouse randomly to generate a random passphrase.": "Please click Next, then move around your mouse randomly to generate a random passphrase.",
"Please go back and check your passphrase again.": "Please go back and check your passphrase again.",
"Please keep it safe!": "Please keep it safe!",
+ "Please sign in with your first passphrase": "Please sign in with your first passphrase",
"Price data currently not available": "Price data currently not available",
"Processing delegate names: ": "Processing delegate names: ",
"Productivity": "Productivity",
@@ -156,15 +161,18 @@
"Report Issue...": "Report Issue...",
"Required": "Required",
"Restart now": "Restart now",
+ "Safekeeping": "Safekeeping",
"Search": "Search",
"Search by username": "Search by username",
"Search for Lisk ID or Transaction ID": "Search for Lisk ID or Transaction ID",
"Search for a delegate": "Search for a delegate",
"Second Signature Creation": "Second Signature Creation",
+ "Secure the use of your Lisk ID with a second passphrase.": "Secure the use of your Lisk ID with a second passphrase.",
"Security": "Security",
"See all transactions": "See all transactions",
"Select a network": "Select a network",
"Select all": "Select all",
+ "Select the missing words to confirm": "Select the missing words to confirm",
"Selection": "Selection",
"Send": "Send",
"Send Lisk from Blockchain Application": "Send Lisk from Blockchain Application",
@@ -182,6 +190,7 @@
"Start here": "Start here",
"Submit": "Submit",
"Success": "Success",
+ "Success!": "Success!",
"Testnet": "Testnet",
"Thank you": "Thank you",
"The Wallet will show your recent transactions.": "The Wallet will show your recent transactions.",
@@ -189,7 +198,9 @@
"The easiest way to do this is to send LSK to yourself. It will cost you only the usual {{fee}} LSK transaction fee.": "The easiest way to do this is to send LSK to yourself. It will cost you only the usual {{fee}} LSK transaction fee.",
"There are no {{filterName}} transactions.": "There are no {{filterName}} transactions.",
"There is a new version ({{version}}) available, do you want to update now?": "There is a new version ({{version}}) available, do you want to update now?",
+ "This is not reversible.": "This is not reversible.",
"This is your Lisk ID": "This is your Lisk ID",
+ "This process should take only 10 seconds but may take up to 15 minutes.": "This process should take only 10 seconds but may take up to 15 minutes.",
"Toggle full screen": "Toggle full screen",
"Total": "Total",
"Total incl. {{fee}} LSK Fee": "Total incl. {{fee}} LSK Fee",
@@ -229,15 +240,19 @@
"You can vote for up to {{count}} delegates in total._plural": "You can vote for up to {{count}} delegates in total.",
"You have already registered as a delegate.": "You have already registered as a delegate.",
"You only need to do this once for each Lisk ID.": "You only need to do this once for each Lisk ID.",
+ "You will need it to use your Lisk ID, like sending and voting. You are responsible for keeping your second passphrase safe. No one can restore it, not even Lisk.": "You will need it to use your Lisk ID, like sending and voting. You are responsible for keeping your second passphrase safe. No one can restore it, not even Lisk.",
"You will send a small amount of {{fee}} LSK to yourself and therefore initialize your ID.": "You will send a small amount of {{fee}} LSK to yourself and therefore initialize your ID.",
"You've received {{value}} LSK.": "You've received {{value}} LSK.",
"Your ID is now secured!": "Your ID is now secured!",
"Your Lisk IDs": "Your Lisk IDs",
+ "Your passphrase is used to access your Lisk ID.": "Your passphrase is used to access your Lisk ID.",
+ "Your registration is secured on the blockchain.": "Your registration is secured on the blockchain.",
+ "Your second passphrase registration is being processed and will be confirmed.": "Your second passphrase registration is being processed and will be confirmed.",
"You’re votes are being processed and will be confirmed. It may take up to 10 minutes to be secured in the blockchain.": "You’re votes are being processed and will be confirmed. It may take up to 10 minutes to be secured in the blockchain.",
"Zero not allowed": "Zero not allowed",
+ "by moving your mouse.": "by moving your mouse.",
+ "by tilting your device.": "by tilting your device.",
"more": "more",
- "set second passphrase": "set second passphrase",
- "your second passphrase will be required for all transactions sent from this account": "your second passphrase will be required for all transactions sent from this account",
"{{count}} delegate names were successfully resolved for unvoting.": "{{count}} delegate name successfully resolved to remove vote from.",
"{{count}} delegate names were successfully resolved for unvoting._plural": "{{count}} delegate names were successfully resolved for unvoting.",
"{{count}} delegate names were successfully resolved for voting.": "{{count}} delegate name successfully resolved to add vote to.",
diff --git a/karma.conf.js b/karma.conf.js
index ee8de78070..eb40f493e0 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -71,7 +71,11 @@ module.exports = function (config) {
'src/components/authenticate/authenticate.js',
'src/components/multiStep/index.js',
'src/components/passphrase/create/index.js',
+ 'src/components/passphrase/createSecond/index.js',
+ 'src/components/passphrase/ConfirmSecond/confirmSecond.js',
+ 'src/components/passphrase/ConfirmSecond/index.js',
'src/components/passphrase/safekeeping/index.js',
+ 'src/components/secondPassphrase/secondPassphrase.js',
'src/components/toolbox/sliderCheckbox/index.js',
'src/components/toolbox/transitionWrapper/index.js',
'src/components/searchBar/index.js',
diff --git a/src/actions/account.js b/src/actions/account.js
index 205ea8a0a3..d6cedda006 100644
--- a/src/actions/account.js
+++ b/src/actions/account.js
@@ -65,9 +65,9 @@ export const passphraseUsed = data => ({
/**
*
*/
-export const secondPassphraseRegistered = ({ activePeer, secondPassphrase, account }) =>
+export const secondPassphraseRegistered = ({ activePeer, secondPassphrase, account, passphrase }) =>
(dispatch) => {
- setSecondPassphrase(activePeer, secondPassphrase, account.publicKey, account.passphrase)
+ setSecondPassphrase(activePeer, secondPassphrase, account.publicKey, passphrase)
.then((data) => {
dispatch(transactionAdded({
id: data.transactionId,
@@ -81,7 +81,7 @@ export const secondPassphraseRegistered = ({ activePeer, secondPassphrase, accou
const text = (error && error.message) ? error.message : i18next.t('An error occurred while registering your second passphrase. Please try again.');
dispatch(errorAlertDialogDisplayed({ text }));
});
- dispatch(passphraseUsed(account.passphrase));
+ dispatch(passphraseUsed(passphrase));
};
/**
diff --git a/src/components/app/index.js b/src/components/app/index.js
index d67b8b6ce5..7cc5f50f19 100644
--- a/src/components/app/index.js
+++ b/src/components/app/index.js
@@ -6,6 +6,7 @@ import Sidechains from '../sidechains';
import Header from '../header';
import Login from '../login';
import Register from '../register';
+import SecondPassphrase from '../secondPassphrase';
import Search from '../search';
import SearchResult from '../search/searchResult';
import TransactionDashboard from '../transactionDashboard';
@@ -46,6 +47,7 @@ class App extends React.Component {
+
diff --git a/src/components/passphrase/ConfirmSecond/confirmSecond.css b/src/components/passphrase/ConfirmSecond/confirmSecond.css
new file mode 100644
index 0000000000..9e1e149783
--- /dev/null
+++ b/src/components/passphrase/ConfirmSecond/confirmSecond.css
@@ -0,0 +1,122 @@
+@import '../../app/variables.css';
+
+@keyframes burst {
+ 0% {
+ opacity: 0;
+ transform: scale(1);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1.1);
+ }
+}
+
+.wrapper {
+ position: absolute;
+ height: calc(100% - 85px) !important;
+ background: #fff;
+ width: 100%;
+ bottom: 0;
+ z-index: 3;
+
+ &.hidden {
+ display: none;
+ }
+
+ & header {
+ height: 50%;
+ width: 100%;
+ display: flex;
+ justify-content: space-around;
+ flex-direction: column;
+ position: relative;
+ z-index: 1;
+
+ &.done {
+ justify-content: flex-end;
+ }
+ }
+
+ & h5 {
+ line-height: 38px;
+ }
+}
+
+.content {
+ position: absolute;
+ height: 50%;
+ border-top: solid 1px #f6f8fb;
+ background: #f6f8fb;
+ box-sizing: border-box;
+ width: 100%;
+ bottom: 0;
+ display: flex;
+ justify-content: space-around;
+ flex-direction: column;
+
+ &.done {
+ background: #fff;
+ border: none;
+ justify-content: baseline;
+ }
+}
+
+.innerContent {
+ margin-top: 45px;
+ padding: 0 50px;
+}
+
+.confirmSlider {
+ width: 250px;
+ margin: 48px auto;
+}
+
+.sliderInput label {
+ width: 275px;
+ margin: 48px auto;
+
+ & div > span {
+ text-indent: 75px;
+ }
+}
+
+.headerIcon {
+ font-size: 68px;
+ color: var(--color-action-light);
+ margin-bottom: 30px;
+}
+
+.resultHeader {
+ margin: 0 auto 10px !important;
+}
+
+.resultButton {
+ margin: 60px auto 0;
+}
+
+.pendingIcon {
+ color: var(--color-grayscale-dark);
+ animation: burst 2000ms infinite linear;
+ animation-direction: alternate;
+ font-size: 120px;
+ margin: 0 auto;
+ transform-origin: 50%;
+ animation-delay: 450ms;
+}
+
+.button {
+ margin-top: 10px;
+}
+
+.sliderInput span.circle {
+ margin-top: 0;
+}
+
+@media (--small-viewport) {
+ .content {
+ position: relative;
+ min-height: 90%;
+ height: auto;
+ }
+}
diff --git a/src/components/passphrase/ConfirmSecond/confirmSecond.js b/src/components/passphrase/ConfirmSecond/confirmSecond.js
new file mode 100644
index 0000000000..e049ef6e22
--- /dev/null
+++ b/src/components/passphrase/ConfirmSecond/confirmSecond.js
@@ -0,0 +1,147 @@
+import React from 'react';
+import { Button } from '../../toolbox/buttons/button';
+import styles from './confirmSecond.css';
+import { passphraseIsValid } from '../../../utils/form';
+import TransitionWrapper from '../../toolbox/transitionWrapper';
+import { FontIcon } from '../../fontIcon';
+import { extractPublicKey } from '../../../utils/api/account';
+// eslint-disable-next-line import/no-named-as-default
+import SliderCheckbox from '../../toolbox/sliderCheckbox';
+// eslint-disable-next-line import/no-named-as-default
+import PassphraseInput from '../../passphraseInput';
+import routes from '../../../constants/routes';
+
+class confirmSecond extends React.Component {
+ constructor() {
+ super();
+ this.state = {
+ step: 'login',
+ passphrase: {
+ value: '',
+ error: '',
+ },
+ };
+ }
+ onChange(name, value, error) {
+ const { publicKey } = this.props.account;
+ if (!error && extractPublicKey(value) !== publicKey) {
+ error = this.props.t('Entered passphrase does not belong to the active account');
+ }
+ this.setState({
+ [name]: {
+ value,
+ error: typeof error === 'string' ? error : undefined,
+ },
+ });
+ }
+ login() {
+ this.setState({
+ step: 'confirm',
+ });
+ }
+ componentDidMount() {
+ if (this.props.account.passphrase) {
+ this.setState({ step: 'confirm' });
+ }
+ }
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.account.secondSignature === 1) {
+ this.setState({ step: 'done' });
+ }
+ }
+ confirm() {
+ const { finalCallback, account } = this.props;
+ const passphrase = this.state.passphrase.value || account.passphrase;
+ finalCallback(passphrase);
+ this.setState({
+ step: 'pending',
+ });
+ }
+ render() {
+ const { hidden, t, history } = this.props;
+ const status = hidden ? styles.hidden : '';
+ const doneClass = (this.state.step === 'done' || this.state.step === 'pending') ? styles.done : '';
+ return (
+
+
+
+ {t('Please sign in with your first passphrase')}
+
+
+
+
+ {t('Great!\nYou’re almost finished')}
+
+
+
+
+
+
+
+
+
+ {t('Success!')}
+
+
+ {t('Your registration is secured on the blockchain.')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('Confirm to register your second passphrase on the blockchain.')}
+
+ {t('This is not reversible.')}
+
+
+
+
+
+
+ {t('Your second passphrase registration is being processed and will be confirmed.')}
+
+ {t('This process should take only 10 seconds but may take up to 15 minutes.')}
+
+
+
+
+
+ );
+ }
+}
+export default confirmSecond;
diff --git a/src/components/passphrase/ConfirmSecond/index.js b/src/components/passphrase/ConfirmSecond/index.js
new file mode 100644
index 0000000000..fa7058c01f
--- /dev/null
+++ b/src/components/passphrase/ConfirmSecond/index.js
@@ -0,0 +1,12 @@
+import { connect } from 'react-redux';
+import { translate } from 'react-i18next';
+import { withRouter } from 'react-router';
+import ConfirmSecond from './confirmSecond';
+
+const mapStateToProps = state => ({
+ account: state.account,
+});
+
+export default withRouter(connect(
+ mapStateToProps,
+)(translate()(ConfirmSecond)));
diff --git a/src/components/passphrase/confirm/index.js b/src/components/passphrase/confirm/index.js
index fe529322f1..169033dab2 100644
--- a/src/components/passphrase/confirm/index.js
+++ b/src/components/passphrase/confirm/index.js
@@ -5,6 +5,7 @@ import { PrimaryButton } from '../../toolbox/buttons/button';
import { extractAddress } from '../../../utils/api/account';
import TransitionWrapper from '../../toolbox/transitionWrapper';
import AccountVisual from '../../accountVisual';
+import SecondPassphraseSteps from '../ConfirmSecond';
class Confirm extends React.Component {
constructor() {
@@ -195,11 +196,11 @@ class Confirm extends React.Component {
-
{this.props.t('Choose the correct phrases to confirm.')}
+
{this.props.t('Select the missing words to confirm')}
-
+ {!this.props.secondPassConfirmation ?
{this.props.t('Perfect! You’re all set.')}
-
+ : null}
{this.props.t('Please go back and check your passphrase again.')}
@@ -243,21 +244,27 @@ class Confirm extends React.Component {