diff --git a/js/src/modals/SMSVerification/SMSVerification.js b/js/src/modals/SMSVerification/SMSVerification.js
index ec5dc7d61..af3153fb9 100644
--- a/js/src/modals/SMSVerification/SMSVerification.js
+++ b/js/src/modals/SMSVerification/SMSVerification.js
@@ -28,6 +28,7 @@ import CheckIfCertified from './CheckIfCertified';
import GatherData from './GatherData';
import SendRequest from './SendRequest';
import QueryCode from './QueryCode';
+import SendConfirmation from './SendConfirmation';
export default class SMSVerification extends Component {
static contextTypes = {
@@ -63,7 +64,7 @@ export default class SMSVerification extends Component {
title='verify your account via SMS'
visible scroll
current={ step }
- steps={ ['Preparations', 'Enter Data', 'Send Request', 'Enter Code'] }
+ steps={ ['Preparations', 'Enter Data', 'Request', 'Enter Code', 'Confirm'] }
>
{ this.renderStep() }
@@ -82,7 +83,7 @@ export default class SMSVerification extends Component {
/>
);
- if (step === 3) {
+ if (step === 4) {
return (
{ cancel }
@@ -116,7 +117,9 @@ export default class SMSVerification extends Component {
}
const { step } = this.state;
- if (step === 3) {
+ if (step === 4) {
+ return this.renderFifthStep();
+ } else if (step === 3) {
return this.renderFourthStep();
} else if (step === 2) {
return this.renderThirdStep();
@@ -195,4 +198,18 @@ export default class SMSVerification extends Component {
/>
);
}
+
+ renderFifthStep () {
+ const { account } = this.props;
+ const { contract, data } = this.state;
+
+ return (
+
+ );
+ }
}
diff --git a/js/src/modals/SMSVerification/SendConfirmation/index.js b/js/src/modals/SMSVerification/SendConfirmation/index.js
new file mode 100644
index 000000000..498a8572e
--- /dev/null
+++ b/js/src/modals/SMSVerification/SendConfirmation/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see
.
+
+export default from './sendConfirmation';
diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css b/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css
new file mode 100644
index 000000000..ac956063c
--- /dev/null
+++ b/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css
@@ -0,0 +1,19 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see
.
+*/
+.spacing {
+ margin-top: 1.5em;
+}
diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js b/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js
new file mode 100644
index 000000000..da0380965
--- /dev/null
+++ b/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js
@@ -0,0 +1,145 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see
.
+
+import React, { Component, PropTypes } from 'react';
+import TxHash from '../../../ui/TxHash';
+
+import { sha3 } from '../../../api/util/sha3';
+
+import styles from './sendConfirmation.css';
+
+const isValidReceipt = (receipt) => {
+ return receipt && receipt.blockNumber && receipt.blockNumber.gt(0);
+};
+
+// TODO: DRY up with ../SendRequest
+const waitForConfirmations = (api, tx, confirmations) => {
+ return new Promise((resolve, reject) => {
+ api.pollMethod('eth_getTransactionReceipt', tx, isValidReceipt)
+ .then((receipt) => {
+ let subscription;
+ api.subscribe('eth_blockNumber', (err, block) => {
+ if (err) {
+ reject(err);
+ } else if (block.minus(confirmations - 1).gte(receipt.blockNumber)) {
+ api.unsubscribe(subscription);
+ resolve();
+ }
+ })
+ .then((_subscription) => {
+ subscription = _subscription;
+ })
+ .catch(reject);
+ });
+ });
+};
+
+export default class SendConfirmation extends Component {
+ static contextTypes = {
+ api: PropTypes.object.isRequired
+ }
+
+ static propTypes = {
+ account: PropTypes.string.isRequired,
+ contract: PropTypes.object.isRequired,
+ data: PropTypes.object.isRequired,
+ onData: PropTypes.func.isRequired,
+ onSuccess: PropTypes.func.isRequired,
+ onError: PropTypes.func.isRequired
+ }
+
+ state = {
+ init: true,
+ step: 'init'
+ };
+
+ componentWillMount () {
+ const { init } = this.state;
+ if (init) {
+ this.send();
+ this.setState({ init: false });
+ }
+ }
+
+ render () {
+ const { step } = this.state;
+
+ if (step === 'error') {
+ return (
{ this.state.error }
);
+ }
+
+ if (step === 'pending') {
+ return (
Waiting for authorization by the Parity Signer.
);
+ }
+
+ if (step === 'posted') {
+ return (
+
+
+
Please keep this window open.
+
);
+ }
+
+ if (step === 'mined') {
+ return (
Congratulations, your account is verified!
);
+ }
+
+ return null;
+ }
+
+ send = () => {
+ const { api } = this.context;
+ const { account, contract, onData, onError, onSuccess } = this.props;
+
+ const { code } = this.props.data;
+ const token = sha3(code);
+
+ const confirm = contract.functions.find((fn) => fn.name === 'confirm');
+ const options = { from: account };
+ const values = [ token ];
+
+ confirm.estimateGas(options, values)
+ .then((gas) => {
+ options.gas = gas.mul(1.2).toFixed(0);
+ // TODO: show message
+ this.setState({ step: 'pending' });
+ return confirm.postTransaction(options, values);
+ })
+ .then((handle) => {
+ // TODO: The "request rejected" error doesn't have any property to
+ // distinguish it from other errors, so we can't give a meaningful error here.
+ return api.pollMethod('parity_checkRequest', handle);
+ })
+ .then((txHash) => {
+ onData({ txHash: txHash });
+ this.setState({ step: 'posted' });
+ return waitForConfirmations(api, txHash, 3);
+ })
+ .then(() => {
+ this.setState({ step: 'mined' });
+ onSuccess();
+ })
+ .catch((err) => {
+ console.error('failed to confirm sms verification', err);
+ onError(err);
+ this.setState({
+ step: 'error',
+ error: 'Failed to send the verification code: ' + err.message
+ });
+ // TODO: show message in SnackBar
+ });
+ }
+}
diff --git a/js/src/modals/SMSVerification/SendRequest/sendRequest.js b/js/src/modals/SMSVerification/SendRequest/sendRequest.js
index 641bd187a..7ca0c2410 100644
--- a/js/src/modals/SMSVerification/SendRequest/sendRequest.js
+++ b/js/src/modals/SMSVerification/SendRequest/sendRequest.js
@@ -25,6 +25,7 @@ const isValidReceipt = (receipt) => {
return receipt && receipt.blockNumber && receipt.blockNumber.gt(0);
};
+// TODO: DRY up with ../SendConfirmation
const waitForConfirmations = (api, tx, confirmations) => {
return new Promise((resolve, reject) => {
api.pollMethod('eth_getTransactionReceipt', tx, isValidReceipt)