factor out SMS-specific logic

This commit is contained in:
Jannis R 2016-12-06 16:09:02 +01:00
parent b5b529f8c2
commit 1672cbad7b
No known key found for this signature in database
GPG Key ID: 0FE83946296A88A5
5 changed files with 83 additions and 54 deletions

View File

@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
import { nullableProptype } from '~/util/proptypes'; import { nullableProptype } from '~/util/proptypes';
import TxHash from '~/ui/TxHash'; import TxHash from '~/ui/TxHash';
import { import {
POSTING_REQUEST, POSTED_REQUEST, REQUESTING_SMS POSTING_REQUEST, POSTED_REQUEST, REQUESTING_CODE
} from '../store'; } from '../store';
import styles from './sendRequest.css'; import styles from './sendRequest.css';
@ -45,9 +45,9 @@ export default class SendRequest extends Component {
</div> </div>
); );
case REQUESTING_SMS: case REQUESTING_CODE:
return ( return (
<p>Requesting an SMS from the Parity server and waiting for the puzzle to be put into the contract.</p> <p>Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.</p>
); );
default: default:

View File

@ -0,0 +1,66 @@
// 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 <http://www.gnu.org/licenses/>.
import { observable, computed, action } from 'mobx';
import phone from 'phoneformat.js';
import VerificationStore, {
LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE
} from './store';
import { postToServer } from '../../3rdparty/sms-verification';
export default class SMSVerificationStore extends VerificationStore {
@observable number = '';
@computed get isNumberValid () {
return phone.isValidNumber(this.number);
}
@computed get isStepValid () {
if (this.step === DONE) {
return true;
}
if (this.error) {
return false;
}
switch (this.step) {
case LOADING:
return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
case QUERY_DATA:
return this.isNumberValid && this.consentGiven;
case QUERY_CODE:
return this.requestTx && this.isCodeValid === true;
case POSTED_CONFIRMATION:
return !!this.confirmationTx;
default:
return false;
}
}
constructor (api, account, isTestnet) {
return super(api, account, isTestnet, 'smsverification');
}
@action setNumber = (number) => {
this.number = number;
}
requestCode = () => {
const { number, account, isTestnet } = this;
return postToServer({ number, address: account }, isTestnet);
}
}

View File

@ -14,14 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { observable, computed, autorun, action } from 'mobx'; import { observable, autorun, action } from 'mobx';
import phone from 'phoneformat.js';
import { sha3 } from '~/api/util/sha3'; import { sha3 } from '~/api/util/sha3';
import Contracts from '~/contracts'; import Contracts from '~/contracts';
import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification'; import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification';
import { postToServer } from '../../3rdparty/sms-verification';
import checkIfTxFailed from '../../util/check-if-tx-failed'; import checkIfTxFailed from '../../util/check-if-tx-failed';
import waitForConfirmations from '../../util/wait-for-block-confirmations'; import waitForConfirmations from '../../util/wait-for-block-confirmations';
@ -29,7 +26,7 @@ export const LOADING = 'fetching-contract';
export const QUERY_DATA = 'query-data'; export const QUERY_DATA = 'query-data';
export const POSTING_REQUEST = 'posting-request'; export const POSTING_REQUEST = 'posting-request';
export const POSTED_REQUEST = 'posted-request'; export const POSTED_REQUEST = 'posted-request';
export const REQUESTING_SMS = 'requesting-sms'; export const REQUESTING_CODE = 'requesting-code';
export const QUERY_CODE = 'query-code'; export const QUERY_CODE = 'query-code';
export const POSTING_CONFIRMATION = 'posting-confirmation'; export const POSTING_CONFIRMATION = 'posting-confirmation';
export const POSTED_CONFIRMATION = 'posted-confirmation'; export const POSTED_CONFIRMATION = 'posted-confirmation';
@ -44,45 +41,18 @@ export default class VerificationStore {
@observable isVerified = null; @observable isVerified = null;
@observable hasRequested = null; @observable hasRequested = null;
@observable consentGiven = false; @observable consentGiven = false;
@observable number = '';
@observable requestTx = null; @observable requestTx = null;
@observable code = ''; @observable code = '';
@observable isCodeValid = null; @observable isCodeValid = null;
@observable confirmationTx = null; @observable confirmationTx = null;
@computed get isNumberValid () { constructor (api, account, isTestnet, name) {
return phone.isValidNumber(this.number);
}
@computed get isStepValid () {
if (this.step === DONE) {
return true;
}
if (this.error) {
return false;
}
switch (this.step) {
case LOADING:
return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
case QUERY_DATA:
return this.isNumberValid && this.consentGiven;
case QUERY_CODE:
return this.requestTx && this.isCodeValid === true;
case POSTED_CONFIRMATION:
return !!this.confirmationTx;
default:
return false;
}
}
constructor (api, account, isTestnet) {
this.api = api; this.api = api;
this.account = account; this.account = account;
this.isTestnet = isTestnet; this.isTestnet = isTestnet;
this.step = LOADING; this.step = LOADING;
Contracts.create(api).registry.getContract('smsverification') Contracts.create(api).registry.getContract(name)
.then((contract) => { .then((contract) => {
this.contract = contract; this.contract = contract;
this.load(); this.load();
@ -93,7 +63,7 @@ export default class VerificationStore {
autorun(() => { autorun(() => {
if (this.error) { if (this.error) {
console.error('sms verification: ' + this.error); console.error('verification: ' + this.error);
} }
}); });
} }
@ -136,10 +106,6 @@ export default class VerificationStore {
}); });
} }
@action setNumber = (number) => {
this.number = number;
}
@action setConsentGiven = (consentGiven) => { @action setConsentGiven = (consentGiven) => {
this.consentGiven = consentGiven; this.consentGiven = consentGiven;
} }
@ -168,7 +134,7 @@ export default class VerificationStore {
} }
@action sendRequest = () => { @action sendRequest = () => {
const { api, account, contract, fee, number, hasRequested } = this; const { api, account, contract, fee, hasRequested } = this;
const request = contract.functions.find((fn) => fn.name === 'request'); const request = contract.functions.find((fn) => fn.name === 'request');
const options = { from: account, value: fee.toString() }; const options = { from: account, value: fee.toString() };
@ -201,18 +167,15 @@ export default class VerificationStore {
chain chain
.then(() => { .then(() => {
return api.parity.netChain(); this.step = REQUESTING_CODE;
}) return this.requestCode();
.then((chain) => {
this.step = REQUESTING_SMS;
return postToServer({ number, address: account }, this.isTestnet);
}) })
.then(() => awaitPuzzle(api, contract, account)) .then(() => awaitPuzzle(api, contract, account))
.then(() => { .then(() => {
this.step = QUERY_CODE; this.step = QUERY_CODE;
}) })
.catch((err) => { .catch((err) => {
this.error = 'Failed to request a confirmation SMS: ' + err.message; this.error = 'Failed to request a confirmation code: ' + err.message;
}); });
} }

View File

@ -25,7 +25,7 @@ import {
LOADING, LOADING,
QUERY_DATA, QUERY_DATA,
POSTING_REQUEST, POSTED_REQUEST, POSTING_REQUEST, POSTED_REQUEST,
REQUESTING_SMS, QUERY_CODE, REQUESTING_CODE, QUERY_CODE,
POSTING_CONFIRMATION, POSTED_CONFIRMATION, POSTING_CONFIRMATION, POSTED_CONFIRMATION,
DONE DONE
} from './store'; } from './store';
@ -47,7 +47,7 @@ export default class Verification extends Component {
static phases = { // mapping (store steps -> steps) static phases = { // mapping (store steps -> steps)
[LOADING]: 0, [LOADING]: 0,
[QUERY_DATA]: 1, [QUERY_DATA]: 1,
[POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_SMS]: 2, [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2,
[QUERY_CODE]: 3, [QUERY_CODE]: 3,
[POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4, [POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4,
[DONE]: 5 [DONE]: 5
@ -60,7 +60,7 @@ export default class Verification extends Component {
return ( return (
<Modal <Modal
actions={ this.renderDialogActions(phase, error, isStepValid) } actions={ this.renderDialogActions(phase, error, isStepValid) }
title='verify your account via SMS' title='verify your account'
visible visible
current={ phase } current={ phase }
steps={ ['Prepare', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] } steps={ ['Prepare', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] }
@ -143,7 +143,7 @@ export default class Verification extends Component {
switch (phase) { switch (phase) {
case 0: case 0:
return ( return (
<p>Loading SMS Verification.</p> <p>Loading Verification.</p>
); );
case 1: case 1:

View File

@ -32,7 +32,7 @@ import Header from './Header';
import Transactions from './Transactions'; import Transactions from './Transactions';
import { setVisibleAccounts } from '~/redux/providers/personalActions'; import { setVisibleAccounts } from '~/redux/providers/personalActions';
import VerificationStore from '~/modals/Verification/store'; import VerificationStore from '~/modals/Verification/sms-store';
import styles from './account.css'; import styles from './account.css';