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)