From 600a7e5ccc84609f8e088d9eb33624cff6ae8bf6 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 6 Dec 2016 15:09:11 +0100 Subject: [PATCH 01/32] make SMS verification contract general purpose --- js/src/contracts/contracts.js | 7 +++++-- js/src/contracts/{sms-verification.js => verification.js} | 0 js/src/modals/SMSVerification/store.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) rename js/src/contracts/{sms-verification.js => verification.js} (100%) diff --git a/js/src/contracts/contracts.js b/js/src/contracts/contracts.js index f61a63690..f30f67efb 100644 --- a/js/src/contracts/contracts.js +++ b/js/src/contracts/contracts.js @@ -19,7 +19,7 @@ import Registry from './registry'; import SignatureReg from './signaturereg'; import TokenReg from './tokenreg'; import GithubHint from './githubhint'; -import * as smsVerification from './sms-verification'; +import * as verification from './verification'; import BadgeReg from './badgereg'; let instance = null; @@ -58,7 +58,10 @@ export default class Contracts { } get smsVerification () { - return smsVerification; + return verification; + } + get emailVerification () { + return verification; } static create (api) { diff --git a/js/src/contracts/sms-verification.js b/js/src/contracts/verification.js similarity index 100% rename from js/src/contracts/sms-verification.js rename to js/src/contracts/verification.js diff --git a/js/src/modals/SMSVerification/store.js b/js/src/modals/SMSVerification/store.js index 49b91fa70..279329ca5 100644 --- a/js/src/modals/SMSVerification/store.js +++ b/js/src/modals/SMSVerification/store.js @@ -20,7 +20,7 @@ import { sha3 } from '~/api/util/sha3'; import Contracts from '~/contracts'; -import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/sms-verification'; +import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification'; import { postToServer } from '../../3rdparty/sms-verification'; import checkIfTxFailed from '../../util/check-if-tx-failed'; import waitForConfirmations from '../../util/wait-for-block-confirmations'; From b5b529f8c2442bbeb6675225f46141dd7a583085 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 6 Dec 2016 15:09:54 +0100 Subject: [PATCH 02/32] modals/SMSVerification -> modals/Verification --- .../modals/{SMSVerification => Verification}/Done/done.css | 0 .../modals/{SMSVerification => Verification}/Done/done.js | 0 .../modals/{SMSVerification => Verification}/Done/index.js | 0 .../GatherData/gatherData.css | 0 .../GatherData/gatherData.js | 0 .../{SMSVerification => Verification}/GatherData/index.js | 0 .../{SMSVerification => Verification}/QueryCode/index.js | 0 .../QueryCode/queryCode.js | 0 .../SendConfirmation/index.js | 0 .../SendConfirmation/sendConfirmation.css | 0 .../SendConfirmation/sendConfirmation.js | 0 .../{SMSVerification => Verification}/SendRequest/index.js | 0 .../SendRequest/sendRequest.css | 0 .../SendRequest/sendRequest.js | 0 js/src/modals/{SMSVerification => Verification}/index.js | 2 +- js/src/modals/{SMSVerification => Verification}/store.js | 0 .../SMSVerification.js => Verification/verification.js} | 4 ++-- js/src/modals/index.js | 4 ++-- js/src/views/Account/account.js | 6 +++--- 19 files changed, 8 insertions(+), 8 deletions(-) rename js/src/modals/{SMSVerification => Verification}/Done/done.css (100%) rename js/src/modals/{SMSVerification => Verification}/Done/done.js (100%) rename js/src/modals/{SMSVerification => Verification}/Done/index.js (100%) rename js/src/modals/{SMSVerification => Verification}/GatherData/gatherData.css (100%) rename js/src/modals/{SMSVerification => Verification}/GatherData/gatherData.js (100%) rename js/src/modals/{SMSVerification => Verification}/GatherData/index.js (100%) rename js/src/modals/{SMSVerification => Verification}/QueryCode/index.js (100%) rename js/src/modals/{SMSVerification => Verification}/QueryCode/queryCode.js (100%) rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/index.js (100%) rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/sendConfirmation.css (100%) rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/sendConfirmation.js (100%) rename js/src/modals/{SMSVerification => Verification}/SendRequest/index.js (100%) rename js/src/modals/{SMSVerification => Verification}/SendRequest/sendRequest.css (100%) rename js/src/modals/{SMSVerification => Verification}/SendRequest/sendRequest.js (100%) rename js/src/modals/{SMSVerification => Verification}/index.js (94%) rename js/src/modals/{SMSVerification => Verification}/store.js (100%) rename js/src/modals/{SMSVerification/SMSVerification.js => Verification/verification.js} (97%) diff --git a/js/src/modals/SMSVerification/Done/done.css b/js/src/modals/Verification/Done/done.css similarity index 100% rename from js/src/modals/SMSVerification/Done/done.css rename to js/src/modals/Verification/Done/done.css diff --git a/js/src/modals/SMSVerification/Done/done.js b/js/src/modals/Verification/Done/done.js similarity index 100% rename from js/src/modals/SMSVerification/Done/done.js rename to js/src/modals/Verification/Done/done.js diff --git a/js/src/modals/SMSVerification/Done/index.js b/js/src/modals/Verification/Done/index.js similarity index 100% rename from js/src/modals/SMSVerification/Done/index.js rename to js/src/modals/Verification/Done/index.js diff --git a/js/src/modals/SMSVerification/GatherData/gatherData.css b/js/src/modals/Verification/GatherData/gatherData.css similarity index 100% rename from js/src/modals/SMSVerification/GatherData/gatherData.css rename to js/src/modals/Verification/GatherData/gatherData.css diff --git a/js/src/modals/SMSVerification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js similarity index 100% rename from js/src/modals/SMSVerification/GatherData/gatherData.js rename to js/src/modals/Verification/GatherData/gatherData.js diff --git a/js/src/modals/SMSVerification/GatherData/index.js b/js/src/modals/Verification/GatherData/index.js similarity index 100% rename from js/src/modals/SMSVerification/GatherData/index.js rename to js/src/modals/Verification/GatherData/index.js diff --git a/js/src/modals/SMSVerification/QueryCode/index.js b/js/src/modals/Verification/QueryCode/index.js similarity index 100% rename from js/src/modals/SMSVerification/QueryCode/index.js rename to js/src/modals/Verification/QueryCode/index.js diff --git a/js/src/modals/SMSVerification/QueryCode/queryCode.js b/js/src/modals/Verification/QueryCode/queryCode.js similarity index 100% rename from js/src/modals/SMSVerification/QueryCode/queryCode.js rename to js/src/modals/Verification/QueryCode/queryCode.js diff --git a/js/src/modals/SMSVerification/SendConfirmation/index.js b/js/src/modals/Verification/SendConfirmation/index.js similarity index 100% rename from js/src/modals/SMSVerification/SendConfirmation/index.js rename to js/src/modals/Verification/SendConfirmation/index.js diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css b/js/src/modals/Verification/SendConfirmation/sendConfirmation.css similarity index 100% rename from js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css rename to js/src/modals/Verification/SendConfirmation/sendConfirmation.css diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js b/js/src/modals/Verification/SendConfirmation/sendConfirmation.js similarity index 100% rename from js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js rename to js/src/modals/Verification/SendConfirmation/sendConfirmation.js diff --git a/js/src/modals/SMSVerification/SendRequest/index.js b/js/src/modals/Verification/SendRequest/index.js similarity index 100% rename from js/src/modals/SMSVerification/SendRequest/index.js rename to js/src/modals/Verification/SendRequest/index.js diff --git a/js/src/modals/SMSVerification/SendRequest/sendRequest.css b/js/src/modals/Verification/SendRequest/sendRequest.css similarity index 100% rename from js/src/modals/SMSVerification/SendRequest/sendRequest.css rename to js/src/modals/Verification/SendRequest/sendRequest.css diff --git a/js/src/modals/SMSVerification/SendRequest/sendRequest.js b/js/src/modals/Verification/SendRequest/sendRequest.js similarity index 100% rename from js/src/modals/SMSVerification/SendRequest/sendRequest.js rename to js/src/modals/Verification/SendRequest/sendRequest.js diff --git a/js/src/modals/SMSVerification/index.js b/js/src/modals/Verification/index.js similarity index 94% rename from js/src/modals/SMSVerification/index.js rename to js/src/modals/Verification/index.js index d9b0990db..9c29a7165 100644 --- a/js/src/modals/SMSVerification/index.js +++ b/js/src/modals/Verification/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default from './SMSVerification'; +export default from './verification'; diff --git a/js/src/modals/SMSVerification/store.js b/js/src/modals/Verification/store.js similarity index 100% rename from js/src/modals/SMSVerification/store.js rename to js/src/modals/Verification/store.js diff --git a/js/src/modals/SMSVerification/SMSVerification.js b/js/src/modals/Verification/verification.js similarity index 97% rename from js/src/modals/SMSVerification/SMSVerification.js rename to js/src/modals/Verification/verification.js index 86f027a52..65447c4f9 100644 --- a/js/src/modals/SMSVerification/SMSVerification.js +++ b/js/src/modals/Verification/verification.js @@ -37,7 +37,7 @@ import SendConfirmation from './SendConfirmation'; import Done from './Done'; @observer -export default class SMSVerification extends Component { +export default class Verification extends Component { static propTypes = { store: PropTypes.any.isRequired, account: PropTypes.string.isRequired, @@ -54,7 +54,7 @@ export default class SMSVerification extends Component { } render () { - const phase = SMSVerification.phases[this.props.store.step]; + const phase = Verification.phases[this.props.store.step]; const { error, isStepValid } = this.props.store; return ( diff --git a/js/src/modals/index.js b/js/src/modals/index.js index 0f0844e40..1daee8663 100644 --- a/js/src/modals/index.js +++ b/js/src/modals/index.js @@ -24,7 +24,7 @@ import EditMeta from './EditMeta'; import ExecuteContract from './ExecuteContract'; import FirstRun from './FirstRun'; import Shapeshift from './Shapeshift'; -import SMSVerification from './SMSVerification'; +import Verification from './Verification'; import Transfer from './Transfer'; import PasswordManager from './PasswordManager'; import SaveContract from './SaveContract'; @@ -42,7 +42,7 @@ export { ExecuteContract, FirstRun, Shapeshift, - SMSVerification, + Verification, Transfer, PasswordManager, LoadContract, diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index 98b0a5e97..1fd654fde 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -23,7 +23,7 @@ import ContentSend from 'material-ui/svg-icons/content/send'; import LockIcon from 'material-ui/svg-icons/action/lock'; import VerifyIcon from 'material-ui/svg-icons/action/verified-user'; -import { EditMeta, DeleteAccount, Shapeshift, SMSVerification, Transfer, PasswordManager } from '~/modals'; +import { EditMeta, DeleteAccount, Shapeshift, Verification, Transfer, PasswordManager } from '~/modals'; import { Actionbar, Button, Page } from '~/ui'; import shapeshiftBtn from '../../../assets/images/shapeshift-btn.png'; @@ -32,7 +32,7 @@ import Header from './Header'; import Transactions from './Transactions'; import { setVisibleAccounts } from '~/redux/providers/personalActions'; -import VerificationStore from '~/modals/SMSVerification/store'; +import VerificationStore from '~/modals/Verification/store'; import styles from './account.css'; @@ -228,7 +228,7 @@ class Account extends Component { const { address } = this.props.params; return ( - From 1672cbad7be46f49af7e2b0b1eaf66b08f9a95a4 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 6 Dec 2016 16:09:02 +0100 Subject: [PATCH 03/32] factor out SMS-specific logic --- .../Verification/SendRequest/sendRequest.js | 6 +- js/src/modals/Verification/sms-store.js | 66 +++++++++++++++++++ js/src/modals/Verification/store.js | 55 +++------------- js/src/modals/Verification/verification.js | 8 +-- js/src/views/Account/account.js | 2 +- 5 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 js/src/modals/Verification/sms-store.js diff --git a/js/src/modals/Verification/SendRequest/sendRequest.js b/js/src/modals/Verification/SendRequest/sendRequest.js index 933de9265..41dc7c06c 100644 --- a/js/src/modals/Verification/SendRequest/sendRequest.js +++ b/js/src/modals/Verification/SendRequest/sendRequest.js @@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react'; import { nullableProptype } from '~/util/proptypes'; import TxHash from '~/ui/TxHash'; import { - POSTING_REQUEST, POSTED_REQUEST, REQUESTING_SMS + POSTING_REQUEST, POSTED_REQUEST, REQUESTING_CODE } from '../store'; import styles from './sendRequest.css'; @@ -45,9 +45,9 @@ export default class SendRequest extends Component { ); - case REQUESTING_SMS: + case REQUESTING_CODE: return ( -

Requesting an SMS from the Parity server and waiting for the puzzle to be put into the contract.

+

Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.

); default: diff --git a/js/src/modals/Verification/sms-store.js b/js/src/modals/Verification/sms-store.js new file mode 100644 index 000000000..58b79ebfb --- /dev/null +++ b/js/src/modals/Verification/sms-store.js @@ -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 . + +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); + } +} diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index 279329ca5..f8542786b 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -14,14 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { observable, computed, autorun, action } from 'mobx'; -import phone from 'phoneformat.js'; +import { observable, autorun, action } from 'mobx'; import { sha3 } from '~/api/util/sha3'; - import Contracts from '~/contracts'; import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification'; -import { postToServer } from '../../3rdparty/sms-verification'; import checkIfTxFailed from '../../util/check-if-tx-failed'; 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 POSTING_REQUEST = 'posting-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 POSTING_CONFIRMATION = 'posting-confirmation'; export const POSTED_CONFIRMATION = 'posted-confirmation'; @@ -44,45 +41,18 @@ export default class VerificationStore { @observable isVerified = null; @observable hasRequested = null; @observable consentGiven = false; - @observable number = ''; @observable requestTx = null; @observable code = ''; @observable isCodeValid = null; @observable confirmationTx = null; - @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) { + constructor (api, account, isTestnet, name) { this.api = api; this.account = account; this.isTestnet = isTestnet; this.step = LOADING; - Contracts.create(api).registry.getContract('smsverification') + Contracts.create(api).registry.getContract(name) .then((contract) => { this.contract = contract; this.load(); @@ -93,7 +63,7 @@ export default class VerificationStore { autorun(() => { 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) => { this.consentGiven = consentGiven; } @@ -168,7 +134,7 @@ export default class VerificationStore { } @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 options = { from: account, value: fee.toString() }; @@ -201,18 +167,15 @@ export default class VerificationStore { chain .then(() => { - return api.parity.netChain(); - }) - .then((chain) => { - this.step = REQUESTING_SMS; - return postToServer({ number, address: account }, this.isTestnet); + this.step = REQUESTING_CODE; + return this.requestCode(); }) .then(() => awaitPuzzle(api, contract, account)) .then(() => { this.step = QUERY_CODE; }) .catch((err) => { - this.error = 'Failed to request a confirmation SMS: ' + err.message; + this.error = 'Failed to request a confirmation code: ' + err.message; }); } diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index 65447c4f9..b05ed353a 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -25,7 +25,7 @@ import { LOADING, QUERY_DATA, POSTING_REQUEST, POSTED_REQUEST, - REQUESTING_SMS, QUERY_CODE, + REQUESTING_CODE, QUERY_CODE, POSTING_CONFIRMATION, POSTED_CONFIRMATION, DONE } from './store'; @@ -47,7 +47,7 @@ export default class Verification extends Component { static phases = { // mapping (store steps -> steps) [LOADING]: 0, [QUERY_DATA]: 1, - [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_SMS]: 2, + [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2, [QUERY_CODE]: 3, [POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4, [DONE]: 5 @@ -60,7 +60,7 @@ export default class Verification extends Component { return ( Loading SMS Verification.

+

Loading Verification.

); case 1: diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index 1fd654fde..240ca2f9b 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -32,7 +32,7 @@ import Header from './Header'; import Transactions from './Transactions'; import { setVisibleAccounts } from '~/redux/providers/personalActions'; -import VerificationStore from '~/modals/Verification/store'; +import VerificationStore from '~/modals/Verification/sms-store'; import styles from './account.css'; From 1ac3421f3327778306c21997e9acdcecde32ad6d Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 6 Dec 2016 17:16:54 +0100 Subject: [PATCH 04/32] step to select verification method --- js/src/modals/Verification/verification.js | 109 ++++++++++++++++----- js/src/views/Account/account.js | 29 ++++-- 2 files changed, 105 insertions(+), 33 deletions(-) diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index b05ed353a..5982933a9 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -20,6 +20,13 @@ import DoneIcon from 'material-ui/svg-icons/action/done-all'; import CancelIcon from 'material-ui/svg-icons/content/clear'; import { Button, IdentityIcon, Modal } from '~/ui'; +import RadioButtons from '~/ui/Form/RadioButtons'; +import { nullableProptype } from '~/util/proptypes'; + +const methods = { + sms: { label: 'SMS Verification', key: 0, value: 'sms' }, + email: { label: 'E-mail Verification', key: 1, value: 'email' } +}; import { LOADING, @@ -39,23 +46,34 @@ import Done from './Done'; @observer export default class Verification extends Component { static propTypes = { - store: PropTypes.any.isRequired, + store: nullableProptype(PropTypes.object).isRequired, account: PropTypes.string.isRequired, + onSelectMethod: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired } static phases = { // mapping (store steps -> steps) - [LOADING]: 0, - [QUERY_DATA]: 1, - [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2, - [QUERY_CODE]: 3, - [POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4, - [DONE]: 5 + [LOADING]: 1, + [QUERY_DATA]: 2, + [POSTING_REQUEST]: 3, [POSTED_REQUEST]: 3, [REQUESTING_CODE]: 3, + [QUERY_CODE]: 4, + [POSTING_CONFIRMATION]: 5, [POSTED_CONFIRMATION]: 5, + [DONE]: 6 } + state = { + method: 'sms' + }; + render () { - const phase = Verification.phases[this.props.store.step]; - const { error, isStepValid } = this.props.store; + const { store } = this.props; + let phase = 0; let error = false; let isStepValid = true; + + if (store) { + phase = Verification.phases[store.step]; + error = store.error; + isStepValid = store.isStepValid; + } return ( { this.renderStep(phase, error) } @@ -85,7 +103,7 @@ export default class Verification extends Component { return (
{ cancel }
); } - if (phase === 5) { + if (phase === 6) { return (
{ cancel } @@ -101,16 +119,23 @@ export default class Verification extends Component { let action = () => {}; switch (phase) { - case 1: - action = store.sendRequest; + case 0: + action = () => { + const { onSelectMethod } = this.props; + const { method } = this.state; + onSelectMethod(method); + }; break; case 2: - action = store.queryCode; + action = store.sendRequest; break; case 3: - action = store.sendConfirmation; + action = store.queryCode; break; case 4: + action = store.sendConfirmation; + break; + case 5: action = store.done; break; } @@ -133,6 +158,19 @@ export default class Verification extends Component { return (

{ error }

); } + if (phase === 0) { + const { method } = this.state; + const values = Object.values(methods); + const value = values.findIndex((v) => v.value === method); + return ( + + ); + } + const { step, fee, number, isNumberValid, isVerified, hasRequested, @@ -141,13 +179,34 @@ export default class Verification extends Component { } = this.props.store; switch (phase) { - case 0: + case 1: return (

Loading Verification.

); - case 1: - const { setNumber, setConsentGiven } = this.props.store; + case 2: + const { method } = this.state; + const { setConsentGiven } = this.props.store; + + const fields = [] + if (method === 'sms') { + fields.push({ + key: 'number', + label: 'phone number in international format', + hint: 'the SMS will be sent to this number', + error: this.props.store.isNumberValid ? null : 'invalid number', + onChange: this.props.store.setNumber + }); + } else if (method === 'email') { + fields.push({ + key: 'email', + label: 'email address', + hint: 'the code will be sent to this address', + error: this.props.store.isEmailValid ? null : 'invalid email', + onChange: this.props.store.setEmail + }); + } + return ( ); - case 2: + case 3: return ( ); - case 3: + case 4: return ( ); - case 4: + case 5: return ( ); - case 5: + case 6: return ( ); @@ -183,4 +242,8 @@ export default class Verification extends Component { return null; } } + + selectMethod = (choice, i) => { + this.setState({ method: choice.value }); + } } diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index 240ca2f9b..3f262bce4 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -32,7 +32,8 @@ import Header from './Header'; import Transactions from './Transactions'; import { setVisibleAccounts } from '~/redux/providers/personalActions'; -import VerificationStore from '~/modals/Verification/sms-store'; +import SMSVerificationStore from '~/modals/Verification/sms-store'; +import EmailVerificationStore from '~/modals/Verification/email-store'; import styles from './account.css'; @@ -72,15 +73,6 @@ class Account extends Component { if (prevAddress !== nextAddress) { this.setVisibleAccounts(nextProps); } - - const { isTestnet } = nextProps; - if (typeof isTestnet === 'boolean' && !this.state.verificationStore) { - const { api } = this.context; - const { address } = nextProps.params; - this.setState({ - verificationStore: new VerificationStore(api, address, isTestnet) - }); - } } componentWillUnmount () { @@ -230,6 +222,7 @@ class Account extends Component { return ( ); @@ -303,6 +296,22 @@ class Account extends Component { this.setState({ showVerificationDialog: true }); } + selectVerificationMethod = (name) => { + const { isTestnet } = this.props; + if (typeof isTestnet !== 'boolean' || this.state.verificationStore) return; + + const { api } = this.context; + const { address } = this.props.params; + + let verificationStore = null; + if (name === 'sms') { + verificationStore = new SMSVerificationStore(api, address, isTestnet); + } else if (name === 'email') { + verificationStore = new EmailVerificationStore(api, address, isTestnet); + } + this.setState({ verificationStore }); + } + onVerificationClose = () => { this.setState({ showVerificationDialog: false }); } From d3fd71d9534ac540d72f7d8263e13a5e8461fa53 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 6 Dec 2016 17:45:34 +0100 Subject: [PATCH 05/32] add email-specific contract, helpers, store --- js/src/3rdparty/email-verification/index.js | 53 +++++++++++++++ js/src/3rdparty/email-verification/styles.css | 20 ++++++ js/src/3rdparty/sms-verification/index.js | 13 ++++ js/src/3rdparty/sms-verification/styles.css | 20 ++++++ js/src/contracts/abi/email-verification.json | 1 + js/src/contracts/abi/index.js | 2 + js/src/modals/Verification/email-store.js | 66 +++++++++++++++++++ 7 files changed, 175 insertions(+) create mode 100644 js/src/3rdparty/email-verification/index.js create mode 100644 js/src/3rdparty/email-verification/styles.css create mode 100644 js/src/3rdparty/sms-verification/styles.css create mode 100644 js/src/contracts/abi/email-verification.json create mode 100644 js/src/modals/Verification/email-store.js diff --git a/js/src/3rdparty/email-verification/index.js b/js/src/3rdparty/email-verification/index.js new file mode 100644 index 000000000..5f4885f3b --- /dev/null +++ b/js/src/3rdparty/email-verification/index.js @@ -0,0 +1,53 @@ +// 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 { stringify } from 'querystring'; +import React from 'react'; + +import styles from './styles.css'; + +export const howItWorks = ( +
+

The following steps will let you prove that you control both an account and an e-mail address.

+
    +
  1. You send a verification request to a specific contract.
  2. +
  3. Our server puts a puzzle into this contract.
  4. +
  5. The code you receive via e-mail is the solution to this puzzle.
  6. +
+
+); + +export const termsOfService = ( +
    +
  • todo
  • +
+); + +export const postToServer = (query, isTestnet = false) => { + const port = isTestnet ? 28443 : 18443; + query = stringify(query); + return fetch(`https://email-verification.parity.io:${port}/?` + query, { + method: 'POST', mode: 'cors', cache: 'no-store' + }) + .then((res) => { + return res.json().then((data) => { + if (res.ok) { + return data.message; + } + throw new Error(data.message || 'unknown error'); + }); + }); +}; diff --git a/js/src/3rdparty/email-verification/styles.css b/js/src/3rdparty/email-verification/styles.css new file mode 100644 index 000000000..daa4c605c --- /dev/null +++ b/js/src/3rdparty/email-verification/styles.css @@ -0,0 +1,20 @@ +/* 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 . +*/ + +.list li { + padding: .1em 0; +} diff --git a/js/src/3rdparty/sms-verification/index.js b/js/src/3rdparty/sms-verification/index.js index c50b2331a..46faf084c 100644 --- a/js/src/3rdparty/sms-verification/index.js +++ b/js/src/3rdparty/sms-verification/index.js @@ -17,6 +17,19 @@ import { stringify } from 'querystring'; import React from 'react'; +import styles from './styles.css'; + +export const howItWorks = ( +
+

The following steps will let you prove that you control both an account and a phone number.

+
    +
  1. You send a verification request to a specific contract.
  2. +
  3. Our server puts a puzzle into this contract.
  4. +
  5. The code you receive via SMS is the solution to this puzzle.
  6. +
+
+); + export const termsOfService = (
  • This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
  • diff --git a/js/src/3rdparty/sms-verification/styles.css b/js/src/3rdparty/sms-verification/styles.css new file mode 100644 index 000000000..daa4c605c --- /dev/null +++ b/js/src/3rdparty/sms-verification/styles.css @@ -0,0 +1,20 @@ +/* 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 . +*/ + +.list li { + padding: .1em 0; +} diff --git a/js/src/contracts/abi/email-verification.json b/js/src/contracts/abi/email-verification.json new file mode 100644 index 000000000..baa6db483 --- /dev/null +++ b/js/src/contracts/abi/email-verification.json @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"reverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"},{"name":"_emailHash","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_emailHash","type":"bytes32"}],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"emailHash","type":"bytes32"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file diff --git a/js/src/contracts/abi/index.js b/js/src/contracts/abi/index.js index f15765b1a..c8cb851dd 100644 --- a/js/src/contracts/abi/index.js +++ b/js/src/contracts/abi/index.js @@ -19,6 +19,7 @@ import basiccoin from './basiccoin.json'; import basiccoinmanager from './basiccoinmanager.json'; import dappreg from './dappreg.json'; import eip20 from './eip20.json'; +import emailverification from './email-verification.json'; import gavcoin from './gavcoin.json'; import githubhint from './githubhint.json'; import owned from './owned.json'; @@ -34,6 +35,7 @@ export { basiccoinmanager, dappreg, eip20, + emailverification, gavcoin, githubhint, owned, diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js new file mode 100644 index 000000000..14179cfe2 --- /dev/null +++ b/js/src/modals/Verification/email-store.js @@ -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 . + +import { observable, computed, action } from 'mobx'; + +import VerificationStore, { + LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE +} from './store'; +import { postToServer } from '../../3rdparty/email-verification'; + +export default class EmailVerificationStore extends VerificationStore { + @observable email = ''; + + @computed get isEmailValid () { + // See https://davidcel.is/posts/stop-validating-email-addresses-with-regex/ + return this.email && this.email.indexOf('@') >= 0; + } + + @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.isEmailValid && 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, 'emailverification'); + } + + @action setEmail = (email) => { + this.email = email; + } + + requestCode = () => { + const { email, account, isTestnet } = this; + return postToServer({ email, address: account }, isTestnet); + } +} From 052f9258a5f1c596adac6e3b2ab490032303da5b Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 7 Dec 2016 11:53:48 +0100 Subject: [PATCH 06/32] pass fields to query into GatherData --- .../Verification/GatherData/gatherData.css | 4 -- .../Verification/GatherData/gatherData.js | 52 +++++++++++-------- js/src/modals/Verification/verification.js | 8 +-- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/js/src/modals/Verification/GatherData/gatherData.css b/js/src/modals/Verification/GatherData/gatherData.css index 680986981..13563b6a5 100644 --- a/js/src/modals/Verification/GatherData/gatherData.css +++ b/js/src/modals/Verification/GatherData/gatherData.css @@ -15,10 +15,6 @@ /* along with Parity. If not, see . */ -.list li { - padding: .1em 0; -} - .spacing { margin-top: 1.5em; } diff --git a/js/src/modals/Verification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js index f5f09578e..24f870fc6 100644 --- a/js/src/modals/Verification/GatherData/gatherData.js +++ b/js/src/modals/Verification/GatherData/gatherData.js @@ -25,41 +25,31 @@ import { fromWei } from '~/api/util/wei'; import { Form, Input } from '~/ui'; import { nullableProptype } from '~/util/proptypes'; -import { termsOfService } from '../../../3rdparty/sms-verification'; +import * as sms from '../../../3rdparty/sms-verification'; +import * as email from '../../../3rdparty/email-verification'; import styles from './gatherData.css'; export default class GatherData extends Component { static propTypes = { fee: React.PropTypes.instanceOf(BigNumber), - isNumberValid: PropTypes.bool.isRequired, + method: PropTypes.string.isRequired, + fields: PropTypes.array.isRequired, isVerified: nullableProptype(PropTypes.bool.isRequired), hasRequested: nullableProptype(PropTypes.bool.isRequired), - setNumber: PropTypes.func.isRequired, setConsentGiven: PropTypes.func.isRequired } render () { - const { isNumberValid, isVerified } = this.props; + const { method, isVerified } = this.props; + const { howItWorks, termsOfService } = method === 'email' ? email : sms; return (
    -

    The following steps will let you prove that you control both an account and a phone number.

    -
      -
    1. You send a verification request to a specific contract.
    2. -
    3. Our server puts a puzzle into this contract.
    4. -
    5. The code you receive via SMS is the solution to this puzzle.
    6. -
    + { howItWorks } { this.renderFee() } { this.renderCertified() } { this.renderRequested() } - + { this.renderFields() } { - this.props.setNumber(value); - } + renderFields () { + const { isVerified, fields } = this.props; - numberOnChange = (_, value) => { - this.props.setNumber(value); + const rendered = fields.map((field) => { + const onChange = (_, v) => { + field.onChange(v); + }; + const onSubmit = field.onChange; + return ( + + ); + }); + + return (
    {rendered}
    ); } consentOnChange = (_, consentGiven) => { diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index 5982933a9..276dfbd1c 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -46,7 +46,7 @@ import Done from './Done'; @observer export default class Verification extends Component { static propTypes = { - store: nullableProptype(PropTypes.object).isRequired, + store: nullableProptype(PropTypes.object.isRequired), account: PropTypes.string.isRequired, onSelectMethod: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired @@ -209,9 +209,9 @@ export default class Verification extends Component { return ( ); From 0e0f602d5e1423eb1665bc794e03e81a1c17fb61 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 7 Dec 2016 19:21:29 +0100 Subject: [PATCH 07/32] pass fields to query into QueryCode --- js/src/modals/Verification/QueryCode/queryCode.js | 13 +++++++++---- js/src/modals/Verification/verification.js | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/js/src/modals/Verification/QueryCode/queryCode.js b/js/src/modals/Verification/QueryCode/queryCode.js index 03b228367..db0ae25eb 100644 --- a/js/src/modals/Verification/QueryCode/queryCode.js +++ b/js/src/modals/Verification/QueryCode/queryCode.js @@ -20,20 +20,25 @@ import { Form, Input } from '~/ui'; export default class QueryCode extends Component { static propTypes = { - number: PropTypes.string.isRequired, + receiver: PropTypes.string.isRequired, + hint: PropTypes.string, isCodeValid: PropTypes.bool.isRequired, setCode: PropTypes.func.isRequired } + static defaultProps = { + hint: 'Enter the code you received.' + } + render () { - const { number, isCodeValid } = this.props; + const { receiver, hint, isCodeValid } = this.props; return ( -

    The verification code has been sent to { number }.

    +

    The verification code has been sent to { receiver }.

    { error }

    ); } + const { method } = this.state; if (phase === 0) { - const { method } = this.state; const values = Object.values(methods); const value = values.findIndex((v) => v.value === method); return ( @@ -185,7 +185,6 @@ export default class Verification extends Component { ); case 2: - const { method } = this.state; const { setConsentGiven } = this.props.store; const fields = [] @@ -221,9 +220,19 @@ export default class Verification extends Component { ); case 4: + let receiver, hint; + if (method === 'sms') { + receiver = this.props.store.number; + hint = 'Enter the code you received via SMS.'; + } else if (method === 'email') { + receiver = this.props.store.email; + hint = 'Enter the code you received via e-mail.'; + } return ( ); From 162420f4c2f790808de5c0086e6990ac84368cd4 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 7 Dec 2016 19:22:13 +0100 Subject: [PATCH 08/32] send emailHash with request, update ABI --- js/src/contracts/abi/email-verification.json | 2 +- js/src/modals/Verification/email-store.js | 5 +++++ js/src/modals/Verification/store.js | 7 +++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/js/src/contracts/abi/email-verification.json b/js/src/contracts/abi/email-verification.json index baa6db483..6a7f5a6d0 100644 --- a/js/src/contracts/abi/email-verification.json +++ b/js/src/contracts/abi/email-verification.json @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"reverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"},{"name":"_emailHash","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_emailHash","type":"bytes32"}],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"emailHash","type":"bytes32"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"reverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"},{"name":"_emailHash","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_emailHash","type":"bytes32"}],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"emailHash","type":"bytes32"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js index 14179cfe2..f0a65300f 100644 --- a/js/src/modals/Verification/email-store.js +++ b/js/src/modals/Verification/email-store.js @@ -15,6 +15,7 @@ // along with Parity. If not, see . import { observable, computed, action } from 'mobx'; +import { sha3 } from '~/api/util/sha3'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE @@ -55,10 +56,14 @@ export default class EmailVerificationStore extends VerificationStore { return super(api, account, isTestnet, 'emailverification'); } + requestValues = () => [ sha3(this.email) ] + @action setEmail = (email) => { this.email = email; } + requestValues = () => [ sha3(this.email) ] + requestCode = () => { const { email, account, isTestnet } = this; return postToServer({ email, address: account }, isTestnet); diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index f8542786b..fc89ad8ac 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -133,19 +133,22 @@ export default class VerificationStore { }); } + requestValues = () => [] + @action sendRequest = () => { const { api, account, contract, fee, hasRequested } = this; const request = contract.functions.find((fn) => fn.name === 'request'); const options = { from: account, value: fee.toString() }; + const values = this.requestValues(); let chain = Promise.resolve(); if (!hasRequested) { this.step = POSTING_REQUEST; - chain = request.estimateGas(options, []) + chain = request.estimateGas(options, values) .then((gas) => { options.gas = gas.mul(1.2).toFixed(0); - return request.postTransaction(options, []); + return request.postTransaction(options, values); }) .then((handle) => { // TODO: The "request rejected" error doesn't have any property to From dfc445b6d66b4752d92e9460dede40df7696b8b2 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 8 Dec 2016 11:55:51 +0100 Subject: [PATCH 09/32] fix bugs & linting issues --- js/src/modals/Verification/email-store.js | 4 +--- js/src/modals/Verification/sms-store.js | 2 +- js/src/modals/Verification/store.js | 2 +- js/src/modals/Verification/verification.js | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js index f0a65300f..5d4ddb4b7 100644 --- a/js/src/modals/Verification/email-store.js +++ b/js/src/modals/Verification/email-store.js @@ -53,7 +53,7 @@ export default class EmailVerificationStore extends VerificationStore { } constructor (api, account, isTestnet) { - return super(api, account, isTestnet, 'emailverification'); + super(api, account, isTestnet, 'emailverification3'); } requestValues = () => [ sha3(this.email) ] @@ -62,8 +62,6 @@ export default class EmailVerificationStore extends VerificationStore { this.email = email; } - requestValues = () => [ sha3(this.email) ] - requestCode = () => { const { email, account, isTestnet } = this; return postToServer({ email, address: account }, isTestnet); diff --git a/js/src/modals/Verification/sms-store.js b/js/src/modals/Verification/sms-store.js index 58b79ebfb..d0f316358 100644 --- a/js/src/modals/Verification/sms-store.js +++ b/js/src/modals/Verification/sms-store.js @@ -52,7 +52,7 @@ export default class SMSVerificationStore extends VerificationStore { } constructor (api, account, isTestnet) { - return super(api, account, isTestnet, 'smsverification'); + super(api, account, isTestnet, 'smsverification'); } @action setNumber = (number) => { diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index fc89ad8ac..88c86e206 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -52,7 +52,7 @@ export default class VerificationStore { this.isTestnet = isTestnet; this.step = LOADING; - Contracts.create(api).registry.getContract(name) + Contracts.get().registry.getContract(name) .then((contract) => { this.contract = contract; this.load(); diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index 094c4d074..cb40d8351 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -173,7 +173,7 @@ export default class Verification extends Component { const { step, - fee, number, isNumberValid, isVerified, hasRequested, + fee, isVerified, hasRequested, requestTx, isCodeValid, confirmationTx, setCode } = this.props.store; @@ -187,7 +187,7 @@ export default class Verification extends Component { case 2: const { setConsentGiven } = this.props.store; - const fields = [] + const fields = []; if (method === 'sms') { fields.push({ key: 'number', From 5418c56b019c934ac850577b0f70aa189b26b240 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 8 Dec 2016 12:11:17 +0100 Subject: [PATCH 10/32] remove Prepare step The modal got really crowded and the preparation step had only been shown for fractions of a second anyways. The "loading" message is now part of the next step. --- js/src/modals/Verification/verification.js | 40 ++++++++++------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index cb40d8351..82792a706 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -53,12 +53,11 @@ export default class Verification extends Component { } static phases = { // mapping (store steps -> steps) - [LOADING]: 1, - [QUERY_DATA]: 2, - [POSTING_REQUEST]: 3, [POSTED_REQUEST]: 3, [REQUESTING_CODE]: 3, - [QUERY_CODE]: 4, - [POSTING_CONFIRMATION]: 5, [POSTED_CONFIRMATION]: 5, - [DONE]: 6 + [LOADING]: 1, [QUERY_DATA]: 1, + [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2, + [QUERY_CODE]: 3, + [POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4, + [DONE]: 5 } state = { @@ -81,8 +80,8 @@ export default class Verification extends Component { title='verify your account' visible current={ phase } - steps={ ['Method', 'Prepare', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] } - waiting={ error ? [] : [ 1, 3, 5 ] } + steps={ ['Method', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] } + waiting={ error ? [] : [ 2, 4 ] } > { this.renderStep(phase, error) } @@ -103,7 +102,7 @@ export default class Verification extends Component { return (
    { cancel }
    ); } - if (phase === 6) { + if (phase === 5) { return (
    { cancel } @@ -126,16 +125,16 @@ export default class Verification extends Component { onSelectMethod(method); }; break; - case 2: + case 1: action = store.sendRequest; break; - case 3: + case 2: action = store.queryCode; break; - case 4: + case 3: action = store.sendConfirmation; break; - case 5: + case 4: action = store.done; break; } @@ -180,11 +179,10 @@ export default class Verification extends Component { switch (phase) { case 1: - return ( -

    Loading Verification.

    - ); + if (step === LOADING) { + return (

    Loading verification data.

    ); + } - case 2: const { setConsentGiven } = this.props.store; const fields = []; @@ -214,12 +212,12 @@ export default class Verification extends Component { /> ); - case 3: + case 2: return ( ); - case 4: + case 3: let receiver, hint; if (method === 'sms') { receiver = this.props.store.number; @@ -237,12 +235,12 @@ export default class Verification extends Component { /> ); - case 5: + case 4: return ( ); - case 6: + case 5: return ( ); From a94bbea7a578a7ddc4adaf4342533a039793d6ca Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 9 Dec 2016 12:37:36 +0100 Subject: [PATCH 11/32] more user-friendly method selection --- js/src/modals/Verification/verification.css | 21 +++++++++++++++++++++ js/src/modals/Verification/verification.js | 12 ++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 js/src/modals/Verification/verification.css diff --git a/js/src/modals/Verification/verification.css b/js/src/modals/Verification/verification.css new file mode 100644 index 000000000..f1a39ac4f --- /dev/null +++ b/js/src/modals/Verification/verification.css @@ -0,0 +1,21 @@ +/* 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 . +*/ + +.noSpacing { + margin-top: 0; + margin-bottom: 0; +} diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index 82792a706..af9a3a45e 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -23,9 +23,17 @@ import { Button, IdentityIcon, Modal } from '~/ui'; import RadioButtons from '~/ui/Form/RadioButtons'; import { nullableProptype } from '~/util/proptypes'; +import styles from './verification.css'; + const methods = { - sms: { label: 'SMS Verification', key: 0, value: 'sms' }, - email: { label: 'E-mail Verification', key: 1, value: 'email' } + sms: { + label: 'SMS Verification', key: 0, value: 'sms', + description: (

    It will be stored on the blockchain that you control a phone number (not which).

    ) + }, + email: { + label: 'E-mail Verification', key: 1, value: 'email', + description: (

    The hash of the e-mail address you prove control over will be stored on the blockchain.

    ) + } }; import { From 452b8c9c74735834ea4a0301f60305b1bf3eabde Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 9 Dec 2016 16:20:35 +0100 Subject: [PATCH 12/32] split sms & email verification 3rdparty code We might want to bundle the code in `3rdparty`. React & presentational components don't belong in there. At the same time, the terms of service are strictly related to the use of these external services. We decided to not bundle them, but still keep them in a file called `terms-of-service.js`. The commit also moves the "how it works" section into the presentational part in `modals/Verification`. --- js/src/3rdparty/email-verification/index.js | 20 --------- js/src/3rdparty/email-verification/styles.css | 20 --------- .../email-verification/terms-of-service.js | 23 +++++++++++ js/src/3rdparty/sms-verification/index.js | 24 ----------- js/src/3rdparty/sms-verification/styles.css | 20 --------- .../sms-verification/terms-of-service.js | 27 ++++++++++++ js/src/contracts/contracts.js | 1 + .../Verification/GatherData/gatherData.js | 8 ++-- js/src/modals/Verification/how-it-works.js | 41 +++++++++++++++++++ js/src/modals/Verification/verification.css | 4 ++ 10 files changed, 101 insertions(+), 87 deletions(-) delete mode 100644 js/src/3rdparty/email-verification/styles.css create mode 100644 js/src/3rdparty/email-verification/terms-of-service.js delete mode 100644 js/src/3rdparty/sms-verification/styles.css create mode 100644 js/src/3rdparty/sms-verification/terms-of-service.js create mode 100644 js/src/modals/Verification/how-it-works.js diff --git a/js/src/3rdparty/email-verification/index.js b/js/src/3rdparty/email-verification/index.js index 5f4885f3b..5b81f3f95 100644 --- a/js/src/3rdparty/email-verification/index.js +++ b/js/src/3rdparty/email-verification/index.js @@ -15,26 +15,6 @@ // along with Parity. If not, see . import { stringify } from 'querystring'; -import React from 'react'; - -import styles from './styles.css'; - -export const howItWorks = ( -
    -

    The following steps will let you prove that you control both an account and an e-mail address.

    -
      -
    1. You send a verification request to a specific contract.
    2. -
    3. Our server puts a puzzle into this contract.
    4. -
    5. The code you receive via e-mail is the solution to this puzzle.
    6. -
    -
    -); - -export const termsOfService = ( -
      -
    • todo
    • -
    -); export const postToServer = (query, isTestnet = false) => { const port = isTestnet ? 28443 : 18443; diff --git a/js/src/3rdparty/email-verification/styles.css b/js/src/3rdparty/email-verification/styles.css deleted file mode 100644 index daa4c605c..000000000 --- a/js/src/3rdparty/email-verification/styles.css +++ /dev/null @@ -1,20 +0,0 @@ -/* 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 . -*/ - -.list li { - padding: .1em 0; -} diff --git a/js/src/3rdparty/email-verification/terms-of-service.js b/js/src/3rdparty/email-verification/terms-of-service.js new file mode 100644 index 000000000..263b7e8f0 --- /dev/null +++ b/js/src/3rdparty/email-verification/terms-of-service.js @@ -0,0 +1,23 @@ +// 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 from 'react'; + +export default ( +
      +
    • todo
    • +
    +); diff --git a/js/src/3rdparty/sms-verification/index.js b/js/src/3rdparty/sms-verification/index.js index 46faf084c..65761223b 100644 --- a/js/src/3rdparty/sms-verification/index.js +++ b/js/src/3rdparty/sms-verification/index.js @@ -15,30 +15,6 @@ // along with Parity. If not, see . import { stringify } from 'querystring'; -import React from 'react'; - -import styles from './styles.css'; - -export const howItWorks = ( -
    -

    The following steps will let you prove that you control both an account and a phone number.

    -
      -
    1. You send a verification request to a specific contract.
    2. -
    3. Our server puts a puzzle into this contract.
    4. -
    5. The code you receive via SMS is the solution to this puzzle.
    6. -
    -
    -); - -export const termsOfService = ( -
      -
    • This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
    • -
    • We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.
    • -
    • You pay a fee for the cost of this service using the account you want to verify.
    • -
    • Your phone number is transmitted to a third party US SMS verification service Twilio for the sole purpose of the SMS verification. You consent to this use. Twilio’s privacy policy is here: https://www.twilio.com/legal/privacy/developer.
    • -
    • Parity Technology Limited is registered in England and Wales under company number 09760015 and complies with the Data Protection Act 1998 (UK). You may contact us via email at admin@parity.io. Our general privacy policy can be found here: https://ethcore.io/legal.html.
    • -
    -); export const postToServer = (query, isTestnet = false) => { const port = isTestnet ? 8443 : 443; diff --git a/js/src/3rdparty/sms-verification/styles.css b/js/src/3rdparty/sms-verification/styles.css deleted file mode 100644 index daa4c605c..000000000 --- a/js/src/3rdparty/sms-verification/styles.css +++ /dev/null @@ -1,20 +0,0 @@ -/* 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 . -*/ - -.list li { - padding: .1em 0; -} diff --git a/js/src/3rdparty/sms-verification/terms-of-service.js b/js/src/3rdparty/sms-verification/terms-of-service.js new file mode 100644 index 000000000..f61b3c97d --- /dev/null +++ b/js/src/3rdparty/sms-verification/terms-of-service.js @@ -0,0 +1,27 @@ +// 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 from 'react'; + +export default ( +
      +
    • This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
    • +
    • We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.
    • +
    • You pay a fee for the cost of this service using the account you want to verify.
    • +
    • Your phone number is transmitted to a third party US SMS verification service Twilio for the sole purpose of the SMS verification. You consent to this use. Twilio’s privacy policy is here: https://www.twilio.com/legal/privacy/developer.
    • +
    • Parity Technology Limited is registered in England and Wales under company number 09760015 and complies with the Data Protection Act 1998 (UK). You may contact us via email at admin@parity.io. Our general privacy policy can be found here: https://ethcore.io/legal.html.
    • +
    +); diff --git a/js/src/contracts/contracts.js b/js/src/contracts/contracts.js index f30f67efb..f21ca9803 100644 --- a/js/src/contracts/contracts.js +++ b/js/src/contracts/contracts.js @@ -60,6 +60,7 @@ export default class Contracts { get smsVerification () { return verification; } + get emailVerification () { return verification; } diff --git a/js/src/modals/Verification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js index 24f870fc6..ecebd4da8 100644 --- a/js/src/modals/Verification/GatherData/gatherData.js +++ b/js/src/modals/Verification/GatherData/gatherData.js @@ -25,8 +25,9 @@ import { fromWei } from '~/api/util/wei'; import { Form, Input } from '~/ui'; import { nullableProptype } from '~/util/proptypes'; -import * as sms from '../../../3rdparty/sms-verification'; -import * as email from '../../../3rdparty/email-verification'; +import smsTermsOfService from '~/3rdparty/sms-verification/terms-of-service'; +import emailTermsOfService from '~/3rdparty/email-verification/terms-of-service'; +import { howSMSVerificationWorks, howEmailVerificationWorks } from '../how-it-works'; import styles from './gatherData.css'; export default class GatherData extends Component { @@ -41,7 +42,8 @@ export default class GatherData extends Component { render () { const { method, isVerified } = this.props; - const { howItWorks, termsOfService } = method === 'email' ? email : sms; + const termsOfService = method === 'email' ? emailTermsOfService : smsTermsOfService; + const howItWorks = method === 'email' ? howEmailVerificationWorks : howSMSVerificationWorks; return ( diff --git a/js/src/modals/Verification/how-it-works.js b/js/src/modals/Verification/how-it-works.js new file mode 100644 index 000000000..6abdc80dd --- /dev/null +++ b/js/src/modals/Verification/how-it-works.js @@ -0,0 +1,41 @@ +// 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 from 'react'; + +import styles from './verification.css'; + +export const howSMSVerificationWorks = ( +
    +

    The following steps will let you prove that you control both an account and a phone number.

    +
      +
    1. You send a verification request to a specific contract.
    2. +
    3. Our server puts a puzzle into this contract.
    4. +
    5. The code you receive via SMS is the solution to this puzzle.
    6. +
    +
    +); + +export const howEmailVerificationWorks = ( +
    +

    The following steps will let you prove that you control both an account and an e-mail address.

    +
      +
    1. You send a verification request to a specific contract.
    2. +
    3. Our server puts a puzzle into this contract.
    4. +
    5. The code you receive via e-mail is the solution to this puzzle.
    6. +
    +
    +); diff --git a/js/src/modals/Verification/verification.css b/js/src/modals/Verification/verification.css index f1a39ac4f..968671e63 100644 --- a/js/src/modals/Verification/verification.css +++ b/js/src/modals/Verification/verification.css @@ -19,3 +19,7 @@ margin-top: 0; margin-bottom: 0; } + +.list li { + padding: .1em 0; +} From c249c51dd3430ba144c7345889f97d863a15d1cb Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 9 Dec 2016 16:40:45 +0100 Subject: [PATCH 13/32] certification: use BadgeReg to load the contract --- js/src/modals/Verification/email-store.js | 3 ++- js/src/modals/Verification/sms-store.js | 3 ++- js/src/modals/Verification/store.js | 10 ++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js index 5d4ddb4b7..3d7faa9e1 100644 --- a/js/src/modals/Verification/email-store.js +++ b/js/src/modals/Verification/email-store.js @@ -17,6 +17,7 @@ import { observable, computed, action } from 'mobx'; import { sha3 } from '~/api/util/sha3'; +import EmailVerificationABI from '~/contracts/abi/email-verification.json'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; @@ -53,7 +54,7 @@ export default class EmailVerificationStore extends VerificationStore { } constructor (api, account, isTestnet) { - super(api, account, isTestnet, 'emailverification3'); + super(api, EmailVerificationABI, 'emailverification3', account, isTestnet); } requestValues = () => [ sha3(this.email) ] diff --git a/js/src/modals/Verification/sms-store.js b/js/src/modals/Verification/sms-store.js index d0f316358..44c5aa39c 100644 --- a/js/src/modals/Verification/sms-store.js +++ b/js/src/modals/Verification/sms-store.js @@ -17,6 +17,7 @@ import { observable, computed, action } from 'mobx'; import phone from 'phoneformat.js'; +import SMSVerificationABI from '~/contracts/abi/sms-verification.json'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; @@ -52,7 +53,7 @@ export default class SMSVerificationStore extends VerificationStore { } constructor (api, account, isTestnet) { - super(api, account, isTestnet, 'smsverification'); + super(api, SMSVerificationABI, 'smsverification', account, isTestnet); } @action setNumber = (number) => { diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index 88c86e206..21213e724 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -16,6 +16,7 @@ import { observable, autorun, action } from 'mobx'; import { sha3 } from '~/api/util/sha3'; +import Contract from '~/api/contract'; import Contracts from '~/contracts'; import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification'; @@ -46,18 +47,19 @@ export default class VerificationStore { @observable isCodeValid = null; @observable confirmationTx = null; - constructor (api, account, isTestnet, name) { + constructor (api, abi, name, account, isTestnet) { this.api = api; this.account = account; this.isTestnet = isTestnet; this.step = LOADING; - Contracts.get().registry.getContract(name) - .then((contract) => { - this.contract = contract; + Contracts.get().badgeReg.fetchCertifier(name) + .then(({ address }) => { + this.contract = new Contract(api, abi).at(address); this.load(); }) .catch((err) => { + console.error('error', err); this.error = 'Failed to fetch the contract: ' + err.message; }); From 592ff53bab593fe5fb0ae3dfc0f2e9cb714fdcaf Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 11 Dec 2016 18:28:37 +0600 Subject: [PATCH 14/32] EIP-155 configuration for Ethereum Classic --- ethcore/res/ethereum/classic.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 7c1e9454e..ca4e0ea99 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -12,7 +12,7 @@ "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "homesteadTransition": "0x118c30", "eip150Transition": "0x2625a0", - "eip155Transition": "0x7fffffffffffffff", + "eip155Transition": 3000000, "eip160Transition": "0x7fffffffffffffff", "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", @@ -25,7 +25,7 @@ "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x1", + "networkID" : "0x3d", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f" }, From 7b5bc115e9b2c5f163760733cf5d426b3cfa08b6 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 11 Dec 2016 18:29:40 +0600 Subject: [PATCH 15/32] EIP-160 configuration for Ethereum Classic --- ethcore/res/ethereum/classic.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index ca4e0ea99..9373a2041 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -13,7 +13,7 @@ "homesteadTransition": "0x118c30", "eip150Transition": "0x2625a0", "eip155Transition": 3000000, - "eip160Transition": "0x7fffffffffffffff", + "eip160Transition": 3000000, "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "ecip1010PauseTransition": "0x2dc6c0", From aed633d7dfe8b3350627aa140b9891306e86ba8d Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 11 Dec 2016 19:25:02 +0600 Subject: [PATCH 16/32] Testnet for Ethereum Classic --- ethcore/res/ethereum/classic-morden.json | 58 ++++++++++++++++++++++++ ethcore/src/ethereum/mod.rs | 3 ++ parity/cli/usage.txt | 4 +- parity/params.rs | 6 +++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 ethcore/res/ethereum/classic-morden.json diff --git a/ethcore/res/ethereum/classic-morden.json b/ethcore/res/ethereum/classic-morden.json new file mode 100644 index 000000000..40c1d4dcf --- /dev/null +++ b/ethcore/res/ethereum/classic-morden.json @@ -0,0 +1,58 @@ +{ + "name": "Ethereum Classic Morden Testnet", + "forkName": "classic", + "engine": { + "Ethash": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", + "homesteadTransition": 494000, + "eip150Transition": 1783000, + "eip155Transition": 1915000, + "eip160Transition": 1915000, + "ecip1010PauseTransition": 1915000, + "ecip1010ContinueTransition": 3415000, + + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff" + } + } + }, + "params": { + "accountStartNonce": "0x0100000", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x3e", + "forkBlock": "0x1b34d8", + "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "nodes": [ + "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303", + "enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303" + ], + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } +} diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 3916e5ccc..4dd0d2b73 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -42,6 +42,9 @@ pub fn new_frontier() -> Spec { load(include_bytes!("../../res/ethereum/frontier /// Create a new Frontier mainnet chain spec without the DAO hardfork. pub fn new_classic() -> Spec { load(include_bytes!("../../res/ethereum/classic.json")) } +/// Create a new Morden chain spec configured for Thereum Classic +pub fn new_classic_morden() -> Spec { load(include_bytes!("../../res/ethereum/classic-morden.json")) } + /// Create a new Frontier mainnet chain spec without the DAO hardfork. pub fn new_expanse() -> Spec { load(include_bytes!("../../res/ethereum/expanse.json")) } diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index c58672542..0a5b854dc 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -33,7 +33,7 @@ Operating Options: --chain CHAIN Specify the blockchain type. CHAIN may be either a JSON chain specification file or olympic, frontier, homestead, mainnet, morden, ropsten, classic, expanse, - testnet or dev (default: {flag_chain}). + testnet, classic-morden or dev (default: {flag_chain}). -d --db-path PATH Specify the database & configuration directory path (default: {flag_db_path}). --keys-path PATH Specify the path for JSON key files to be found @@ -266,7 +266,7 @@ Footprint Options: of all accounts and storage keys. Doubles the size of the state database. BOOL may be one of on, off or auto. (default: {flag_fat_db}) - --scale-verifiers Automatically scale amount of verifier threads based on + --scale-verifiers Automatically scale amount of verifier threads based on workload. Not guaranteed to be faster. (default: {flag_scale_verifiers}) --num-verifiers INT Amount of verifier threads to use or to begin with, if verifier diff --git a/parity/params.rs b/parity/params.rs index 25ddc8814..d8c3db2bc 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -31,6 +31,7 @@ pub enum SpecType { Ropsten, Olympic, Classic, + ClassicTestnet, Expanse, Dev, Custom(String), @@ -49,6 +50,7 @@ impl str::FromStr for SpecType { let spec = match s { "frontier" | "homestead" | "mainnet" => SpecType::Mainnet, "frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic, + "classic-testnet" | "classic-morden" => SpecType::ClassicTestnet, "morden" | "testnet" => SpecType::Testnet, "ropsten" => SpecType::Ropsten, "olympic" => SpecType::Olympic, @@ -68,6 +70,7 @@ impl SpecType { SpecType::Ropsten => Ok(ethereum::new_ropsten()), SpecType::Olympic => Ok(ethereum::new_olympic()), SpecType::Classic => Ok(ethereum::new_classic()), + SpecType::ClassicTestnet => Ok(ethereum::new_classic_morden()), SpecType::Expanse => Ok(ethereum::new_expanse()), SpecType::Dev => Ok(Spec::new_instant()), SpecType::Custom(ref filename) => { @@ -288,6 +291,9 @@ mod tests { assert_eq!(SpecType::Testnet, "morden".parse().unwrap()); assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap()); assert_eq!(SpecType::Olympic, "olympic".parse().unwrap()); + assert_eq!(SpecType::Classic, "classic".parse().unwrap()); + assert_eq!(SpecType::ClassicTestnet, "classic-testnet".parse().unwrap()); + assert_eq!(SpecType::ClassicTestnet, "classic-morden".parse().unwrap()); } #[test] From 4e3c49c809589d4347c350af599951eb3c1995ae Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 11 Dec 2016 20:34:46 +0600 Subject: [PATCH 17/32] revert ETC to correct Network ID --- ethcore/res/ethereum/classic-morden.json | 2 +- ethcore/res/ethereum/classic.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/res/ethereum/classic-morden.json b/ethcore/res/ethereum/classic-morden.json index 40c1d4dcf..bc0bf4c02 100644 --- a/ethcore/res/ethereum/classic-morden.json +++ b/ethcore/res/ethereum/classic-morden.json @@ -26,7 +26,7 @@ "accountStartNonce": "0x0100000", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x3e", + "networkID" : "0x2", "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145" }, diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 9373a2041..9c189e8d8 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -25,7 +25,7 @@ "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x3d", + "networkID" : "0x1", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f" }, From 6742b080f556def243e1151631355b79c330289e Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 11 Dec 2016 20:38:37 +0600 Subject: [PATCH 18/32] use decimals for block numbers in config --- ethcore/res/ethereum/classic.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 9c189e8d8..a08dde33b 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -10,14 +10,15 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "homesteadTransition": "0x118c30", - "eip150Transition": "0x2625a0", + "homesteadTransition": 1150000, + "eip150Transition": 2500000, "eip155Transition": 3000000, "eip160Transition": 3000000, + "ecip1010PauseTransition": 3000000, + "ecip1010ContinueTransition": 5000000, + "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "ecip1010PauseTransition": "0x2dc6c0", - "ecip1010ContinueTransition": "0x4c4b40" + "eip161dTransition": "0x7fffffffffffffff" } } }, From 2c4c6ba4e4f89b787b7bbe2aa38c36dbe54e23ac Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 10:12:12 +0100 Subject: [PATCH 19/32] Basic smoketest --- js/src/ui/Form/TypedInput/typedInput.spec.js | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 js/src/ui/Form/TypedInput/typedInput.spec.js diff --git a/js/src/ui/Form/TypedInput/typedInput.spec.js b/js/src/ui/Form/TypedInput/typedInput.spec.js new file mode 100644 index 000000000..c86c94237 --- /dev/null +++ b/js/src/ui/Form/TypedInput/typedInput.spec.js @@ -0,0 +1,47 @@ +// Copyright 2015, 2016 Parity Technologies (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 { mount } from 'enzyme'; +import React from 'react'; +import sinon from 'sinon'; + +import { ContextProvider, muiTheme } from '~/ui'; +import { ABI_TYPES } from '~/util/abi'; + +import TypedInput from './'; + +let component; +let onChange; + +function render (props) { + onChange = sinon.stub(); + component = mount( + + + + ); + + console.log(component.debug()); + return component; +} + +describe.only('ui/Form/TypedInput', () => { + it('renders defaults', () => { + expect(render({ param: { type: ABI_TYPES.BOOL } })).to.be.ok; + }); +}); From 28be8d6f6c799fb5b756f1d362562ff488714d1d Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 10:55:20 +0100 Subject: [PATCH 20/32] Test for bool TypedInput --- js/src/ui/Form/Select/select.js | 14 +++++----- js/src/ui/Form/TypedInput/typedInput.js | 17 +++++++----- js/src/ui/Form/TypedInput/typedInput.spec.js | 29 ++++++++++++++++++-- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/js/src/ui/Form/Select/select.js b/js/src/ui/Form/Select/select.js index c6dae8b61..f79cae58c 100644 --- a/js/src/ui/Form/Select/select.js +++ b/js/src/ui/Form/Select/select.js @@ -46,26 +46,26 @@ export default class Select extends Component { } render () { - const { disabled, error, label, hint, value, children, className, onBlur, onChange, onKeyDown } = this.props; + const { children, className, disabled, error, hint, label, onBlur, onChange, onKeyDown, value } = this.props; return ( + onKeyDown={ onKeyDown } + underlineDisabledStyle={ UNDERLINE_DISABLED } + underlineStyle={ UNDERLINE_NORMAL } + value={ value }> { children } ); diff --git a/js/src/ui/Form/TypedInput/typedInput.js b/js/src/ui/Form/TypedInput/typedInput.js index 6383e62bc..3d21dd6d7 100644 --- a/js/src/ui/Form/TypedInput/typedInput.js +++ b/js/src/ui/Form/TypedInput/typedInput.js @@ -289,9 +289,8 @@ export default class TypedInput extends Component { return ( + value={ bool }> { bool } ); @@ -299,19 +298,23 @@ export default class TypedInput extends Component { return ( ); } onChangeBool = (event, _index, value) => { - this.props.onChange(value === 'true'); + // NOTE: event.target.value added for enzyme simulated event testing + this.props.onChange((value || event.target.value) === 'true'); } onEthTypeChange = () => { diff --git a/js/src/ui/Form/TypedInput/typedInput.spec.js b/js/src/ui/Form/TypedInput/typedInput.spec.js index c86c94237..151c88104 100644 --- a/js/src/ui/Form/TypedInput/typedInput.spec.js +++ b/js/src/ui/Form/TypedInput/typedInput.spec.js @@ -36,12 +36,35 @@ function render (props) { ); - console.log(component.debug()); return component; } describe.only('ui/Form/TypedInput', () => { - it('renders defaults', () => { - expect(render({ param: { type: ABI_TYPES.BOOL } })).to.be.ok; + describe('bool selection', () => { + beforeEach(() => { + render({ param: { type: ABI_TYPES.BOOL } }); + }); + + it('renders', () => { + expect(component).to.be.ok; + }); + + it('calls onChange when value changes', () => { + component.find('DropDownMenu').simulate('change', { target: { value: 'true' } }); + + expect(onChange).to.have.been.called; + }); + + it("calls onChange(true) when value changes to 'true'", () => { + component.find('DropDownMenu').simulate('change', { target: { value: 'true' } }); + + expect(onChange).to.have.been.calledWith(true); + }); + + it("calls onChange(false) when value changes to 'false'", () => { + component.find('DropDownMenu').simulate('change', { target: { value: 'false' } }); + + expect(onChange).to.have.been.calledWith(false); + }); }); }); From c43944584df38ea5ea8187d6b3b86ccbdde64620 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Mon, 12 Dec 2016 12:33:58 +0100 Subject: [PATCH 21/32] fix import --- js/src/modals/Verification/store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index 4508289a6..dcbfbf698 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -19,7 +19,7 @@ import { sha3 } from '~/api/util/sha3'; import Contract from '~/api/contract'; import Contracts from '~/contracts'; -import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/sms-verification'; +import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification'; import { checkIfTxFailed, waitForConfirmations } from '~/util/tx'; export const LOADING = 'fetching-contract'; From 23234fb1aa80c115efac84e1a4c7a6947b54411c Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 12:48:16 +0100 Subject: [PATCH 22/32] Allow operation in test mode --- js/src/api/util/identity.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/js/src/api/util/identity.js b/js/src/api/util/identity.js index 6a25590e3..e4a95891f 100644 --- a/js/src/api/util/identity.js +++ b/js/src/api/util/identity.js @@ -1,9 +1,30 @@ +// Copyright 2015, 2016 Parity Technologies (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 blockies from 'blockies'; +// jsdom doesn't have all the browser features, blockies fail +const TEST_ENV = process.env.NODE_ENV === 'test'; + export function createIdentityImg (address, scale = 8) { - return blockies({ - seed: (address || '').toLowerCase(), - size: 8, - scale - }).toDataURL(); + return TEST_ENV + ? '' + : blockies({ + seed: (address || '').toLowerCase(), + size: 8, + scale + }).toDataURL(); } From 29674a0e65a6ee28774b5f0adc6b29d48b01dc1d Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 12:48:32 +0100 Subject: [PATCH 23/32] Small testability fixes --- js/src/ui/IdentityIcon/identityIcon.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/js/src/ui/IdentityIcon/identityIcon.js b/js/src/ui/IdentityIcon/identityIcon.js index 466ffa9b5..55fc34afa 100644 --- a/js/src/ui/IdentityIcon/identityIcon.js +++ b/js/src/ui/IdentityIcon/identityIcon.js @@ -19,6 +19,8 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import ContractIcon from 'material-ui/svg-icons/action/code'; +import { createIdentityImg } from '~/api/util/identity'; + import styles from './identityIcon.css'; class IdentityIcon extends Component { @@ -29,12 +31,12 @@ class IdentityIcon extends Component { static propTypes = { address: PropTypes.string, button: PropTypes.bool, - className: PropTypes.string, center: PropTypes.bool, - padded: PropTypes.bool, + className: PropTypes.string, inline: PropTypes.bool, - tiny: PropTypes.bool, - images: PropTypes.object.isRequired + images: PropTypes.object.isRequired, + padded: PropTypes.bool, + tiny: PropTypes.bool } state = { @@ -75,7 +77,7 @@ class IdentityIcon extends Component { } this.setState({ - iconsrc: api.util.createIdentityImg(_address, scale) + iconsrc: createIdentityImg(_address, scale) }); } @@ -105,16 +107,20 @@ class IdentityIcon extends Component { return ( + style={ { + width: size, + height: size, + background: '#eee' + } } /> ); } return ( + src={ iconsrc } /> ); } } From c5c4e5e901e5aef9175ccb98ee0469330aef18d2 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 12:48:43 +0100 Subject: [PATCH 24/32] Updated --- js/src/ui/Form/TypedInput/typedInput.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/ui/Form/TypedInput/typedInput.spec.js b/js/src/ui/Form/TypedInput/typedInput.spec.js index 151c88104..e27c7482a 100644 --- a/js/src/ui/Form/TypedInput/typedInput.spec.js +++ b/js/src/ui/Form/TypedInput/typedInput.spec.js @@ -39,7 +39,7 @@ function render (props) { return component; } -describe.only('ui/Form/TypedInput', () => { +describe('ui/Form/TypedInput', () => { describe('bool selection', () => { beforeEach(() => { render({ param: { type: ABI_TYPES.BOOL } }); From 563c8c75f94420d1d365738576fa63c81e901cab Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 12:49:04 +0100 Subject: [PATCH 25/32] Tests for DetailsStep (only bool dropdown) --- .../DetailsStep/detailsStep.js | 18 ++-- .../DetailsStep/detailsStep.spec.js | 83 +++++++++++++++++++ 2 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 js/src/modals/ExecuteContract/DetailsStep/detailsStep.spec.js diff --git a/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js b/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js index ae3c92e48..0e54e9ef4 100644 --- a/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js +++ b/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js @@ -58,23 +58,23 @@ export default class DetailsStep extends Component { { this.renderWarning() } + error={ fromAddressError } + hint='the account to transact with' + label='from account' + onChange={ onFromAddressChange } + value={ fromAddress } /> { this.renderFunctionSelect() } { this.renderParameters() }
    + hint='the amount to send to with the transaction' + label='transaction value (in ETH)' + onSubmit={ onAmountChange } + value={ amount } />
    . + +import { mount } from 'enzyme'; +import React from 'react'; +import sinon from 'sinon'; + +import { ContextProvider, muiTheme } from '~/ui'; + +import DetailsStep from './'; + +import { CONTRACT } from '../executeContract.test.js'; + +let component; +let onAmountChange; +let onClose; +let onFromAddressChange; +let onFuncChange; +let onGasEditClick; +let onValueChange; + +function render (props) { + onAmountChange = sinon.stub(); + onClose = sinon.stub(); + onFromAddressChange = sinon.stub(); + onFuncChange = sinon.stub(); + onGasEditClick = sinon.stub(); + onValueChange = sinon.stub(); + + component = mount( + + + + ); + + return component; +} + +describe('modals/ExecuteContract/DetailsStep', () => { + it('renders', () => { + expect(render({ accounts: {}, values: [ true ], valuesError: [ null ] })).to.be.ok; + }); + + describe('parameter values', () => { + beforeEach(() => { + render({ + accounts: {}, + func: CONTRACT.functions[0], + values: [ false ], + valuesError: [ null ] + }); + }); + + describe('bool parameters', () => { + it('toggles from false to true', () => { + component.find('DropDownMenu').last().simulate('change', { target: { value: 'true' } }); + + expect(onValueChange).to.have.been.calledWith(null, 0, true); + }); + }); + }); +}); From 3a7e30ec5cda466d5df4f642781f9e4ae4b7bd93 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 12 Dec 2016 12:49:40 +0100 Subject: [PATCH 26/32] Fix issue with bool type dropdown --- .../modals/ExecuteContract/executeContract.js | 20 +++--- .../ExecuteContract/executeContract.spec.js | 69 +++++++++++++++++++ .../ExecuteContract/executeContract.test.js | 64 +++++++++++++++++ 3 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 js/src/modals/ExecuteContract/executeContract.spec.js create mode 100644 js/src/modals/ExecuteContract/executeContract.test.js diff --git a/js/src/modals/ExecuteContract/executeContract.js b/js/src/modals/ExecuteContract/executeContract.js index afcc826b7..74f36df34 100644 --- a/js/src/modals/ExecuteContract/executeContract.js +++ b/js/src/modals/ExecuteContract/executeContract.js @@ -25,6 +25,7 @@ import ContentClear from 'material-ui/svg-icons/content/clear'; import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back'; import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward'; +import { toWei } from '~/api/util/wei'; import { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash } from '~/ui'; import { MAX_GAS_ESTIMATION } from '~/util/constants'; import { validateAddress, validateUint } from '~/util/validation'; @@ -56,12 +57,12 @@ class ExecuteContract extends Component { } static propTypes = { - isTest: PropTypes.bool, - fromAddress: PropTypes.string, accounts: PropTypes.object, balances: PropTypes.object, - contract: PropTypes.object, + contract: PropTypes.object.isRequired, + fromAddress: PropTypes.string, gasLimit: PropTypes.object.isRequired, + isTest: PropTypes.bool, onClose: PropTypes.func.isRequired, onFromAddressChange: PropTypes.func.isRequired } @@ -77,11 +78,11 @@ class ExecuteContract extends Component { funcError: null, gasEdit: false, rejected: false, - step: STEP_DETAILS, sending: false, + step: STEP_DETAILS, + txhash: null, values: [], - valuesError: [], - txhash: null + valuesError: [] } componentDidMount () { @@ -255,10 +256,6 @@ class ExecuteContract extends Component { valueError = validateAddress(_value).addressError; break; - case 'bool': - value = _value === 'true'; - break; - case 'uint': valueError = validateUint(_value).valueError; break; @@ -278,13 +275,12 @@ class ExecuteContract extends Component { } estimateGas = (_fromAddress) => { - const { api } = this.context; const { fromAddress } = this.props; const { amount, func, values } = this.state; const options = { gas: MAX_GAS_ESTIMATION, from: _fromAddress || fromAddress, - value: api.util.toWei(amount || 0) + value: toWei(amount || 0) }; if (!func) { diff --git a/js/src/modals/ExecuteContract/executeContract.spec.js b/js/src/modals/ExecuteContract/executeContract.spec.js new file mode 100644 index 000000000..6a8cc692d --- /dev/null +++ b/js/src/modals/ExecuteContract/executeContract.spec.js @@ -0,0 +1,69 @@ +// Copyright 2015, 2016 Parity Technologies (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 { shallow } from 'enzyme'; +import React from 'react'; +import sinon from 'sinon'; + +import ExecuteContract from './'; + +import { CONTRACT, STORE } from './executeContract.test.js'; + +let component; +let onClose; +let onFromAddressChange; + +function render (props) { + onClose = sinon.stub(); + onFromAddressChange = sinon.stub(); + + component = shallow( + , + { context: { api: {}, store: STORE } } + ).find('ExecuteContract').shallow(); + + return component; +} + +describe('modals/ExecuteContract/DetailsStep', () => { + it('renders', () => { + expect(render({ accounts: {} })).to.be.ok; + }); + + describe('instance functions', () => { + beforeEach(() => { + render({ + accounts: {} + }); + }); + + describe('onValueChange', () => { + it('toggles boolean from false to true', () => { + component.setState({ + func: CONTRACT.functions[0], + values: [false] + }); + component.instance().onValueChange(null, 0, true); + + expect(component.state().values).to.deep.equal([true]); + }); + }); + }); +}); diff --git a/js/src/modals/ExecuteContract/executeContract.test.js b/js/src/modals/ExecuteContract/executeContract.test.js new file mode 100644 index 000000000..212aba2c8 --- /dev/null +++ b/js/src/modals/ExecuteContract/executeContract.test.js @@ -0,0 +1,64 @@ +// Copyright 2015, 2016 Parity Technologies (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 BigNumber from 'bignumber.js'; +import sinon from 'sinon'; + +const CONTRACT = { + functions: [ + { + name: 'test_a', + signature: 'test_a', + estimateGas: sinon.stub().resolves(new BigNumber(123)), + inputs: [ + { + name: 'test_bool', + kind: { + type: 'bool' + } + } + ], + abi: { + inputs: [ + { + name: 'test_bool', + type: 'bool' + } + ] + } + } + ] +}; + +const STORE = { + dispatch: sinon.stub(), + subscribe: sinon.stub(), + getState: () => { + return { + balances: { + balances: {} + }, + nodeStatus: { + gasLimit: new BigNumber(123) + } + }; + } +}; + +export { + CONTRACT, + STORE +}; From d2a34acdfdc142ed35002e0db80018529f24c0ac Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 12 Dec 2016 14:37:25 +0000 Subject: [PATCH 27/32] [ci skip] js-precompiled 20161212-143454 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb86cd47b..316978f20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1290,7 +1290,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#eb9d978ed5ad1c514b37e89c716f80b3c8d613b5" +source = "git+https://github.com/ethcore/js-precompiled.git#b29e2a151561ae41aa27af3b226522844ae8aae2" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 95b15bb83..5cbdd6bf3 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.119", + "version": "0.2.120", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From e61d14d7f7658d331b41c3d123a7a79556c4088f Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Mon, 12 Dec 2016 19:50:32 +0000 Subject: [PATCH 28/32] reuse Morden for Classic Testnet --- ethcore/res/ethereum/classic-morden.json | 58 ------------------------ ethcore/res/ethereum/morden.json | 15 +++--- ethcore/res/ethereum/tests | 2 +- ethcore/src/ethereum/mod.rs | 3 -- parity/cli/usage.txt | 2 +- parity/params.rs | 8 +--- 6 files changed, 13 insertions(+), 75 deletions(-) delete mode 100644 ethcore/res/ethereum/classic-morden.json diff --git a/ethcore/res/ethereum/classic-morden.json b/ethcore/res/ethereum/classic-morden.json deleted file mode 100644 index bc0bf4c02..000000000 --- a/ethcore/res/ethereum/classic-morden.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "Ethereum Classic Morden Testnet", - "forkName": "classic", - "engine": { - "Ethash": { - "params": { - "gasLimitBoundDivisor": "0x0400", - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", - "registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", - "homesteadTransition": 494000, - "eip150Transition": 1783000, - "eip155Transition": 1915000, - "eip160Transition": 1915000, - "ecip1010PauseTransition": 1915000, - "ecip1010ContinueTransition": 3415000, - - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" - } - } - }, - "params": { - "accountStartNonce": "0x0100000", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID" : "0x2", - "forkBlock": "0x1b34d8", - "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x00006d6f7264656e", - "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" - } - }, - "difficulty": "0x20000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x", - "gasLimit": "0x2fefd8" - }, - "nodes": [ - "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303", - "enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } - } -} diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index 6e725e8bf..d24e0ec0c 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -9,12 +9,15 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", - "homesteadTransition": "0x789b0", - "eip150Transition": "0x1b34d8", - "eip155Transition": 1885000, - "eip160Transition": 1885000, - "eip161abcTransition": 1885000, - "eip161dTransition": 1885000 + "homesteadTransition": 494000, + "eip150Transition": 1783000, + "eip155Transition": 1915000, + "eip160Transition": 1915000, + "ecip1010PauseTransition": 1915000, + "ecip1010ContinueTransition": 3415000, + + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff" } } }, diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index e8f4624b7..9028c4801 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be +Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8 diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 4dd0d2b73..3916e5ccc 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -42,9 +42,6 @@ pub fn new_frontier() -> Spec { load(include_bytes!("../../res/ethereum/frontier /// Create a new Frontier mainnet chain spec without the DAO hardfork. pub fn new_classic() -> Spec { load(include_bytes!("../../res/ethereum/classic.json")) } -/// Create a new Morden chain spec configured for Thereum Classic -pub fn new_classic_morden() -> Spec { load(include_bytes!("../../res/ethereum/classic-morden.json")) } - /// Create a new Frontier mainnet chain spec without the DAO hardfork. pub fn new_expanse() -> Spec { load(include_bytes!("../../res/ethereum/expanse.json")) } diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 0a5b854dc..1e99c76fe 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -33,7 +33,7 @@ Operating Options: --chain CHAIN Specify the blockchain type. CHAIN may be either a JSON chain specification file or olympic, frontier, homestead, mainnet, morden, ropsten, classic, expanse, - testnet, classic-morden or dev (default: {flag_chain}). + testnet or dev (default: {flag_chain}). -d --db-path PATH Specify the database & configuration directory path (default: {flag_db_path}). --keys-path PATH Specify the path for JSON key files to be found diff --git a/parity/params.rs b/parity/params.rs index d8c3db2bc..99ceac67b 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -31,7 +31,6 @@ pub enum SpecType { Ropsten, Olympic, Classic, - ClassicTestnet, Expanse, Dev, Custom(String), @@ -50,8 +49,7 @@ impl str::FromStr for SpecType { let spec = match s { "frontier" | "homestead" | "mainnet" => SpecType::Mainnet, "frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic, - "classic-testnet" | "classic-morden" => SpecType::ClassicTestnet, - "morden" | "testnet" => SpecType::Testnet, + "morden" | "testnet" | "classic-testnet" => SpecType::Testnet, "ropsten" => SpecType::Ropsten, "olympic" => SpecType::Olympic, "expanse" => SpecType::Expanse, @@ -70,7 +68,6 @@ impl SpecType { SpecType::Ropsten => Ok(ethereum::new_ropsten()), SpecType::Olympic => Ok(ethereum::new_olympic()), SpecType::Classic => Ok(ethereum::new_classic()), - SpecType::ClassicTestnet => Ok(ethereum::new_classic_morden()), SpecType::Expanse => Ok(ethereum::new_expanse()), SpecType::Dev => Ok(Spec::new_instant()), SpecType::Custom(ref filename) => { @@ -292,8 +289,7 @@ mod tests { assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap()); assert_eq!(SpecType::Olympic, "olympic".parse().unwrap()); assert_eq!(SpecType::Classic, "classic".parse().unwrap()); - assert_eq!(SpecType::ClassicTestnet, "classic-testnet".parse().unwrap()); - assert_eq!(SpecType::ClassicTestnet, "classic-morden".parse().unwrap()); + assert_eq!(SpecType::Testnet, "classic-testnet".parse().unwrap()); } #[test] From 1114ad3ca701ebb13100c34be81ac73bbaafad09 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 13 Dec 2016 05:15:44 +0000 Subject: [PATCH 29/32] [ci skip] js-precompiled 20161213-051314 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 316978f20..9095934c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1290,7 +1290,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#b29e2a151561ae41aa27af3b226522844ae8aae2" +source = "git+https://github.com/ethcore/js-precompiled.git#a8f4db707c521f71f093b62e3173b98144569c4e" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 5cbdd6bf3..36cd9ad5a 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.120", + "version": "0.2.121", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From f47be5084370e5ee1f64621fb605c7f0559e20a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Dec 2016 14:27:27 +0100 Subject: [PATCH 30/32] Using jsonrpc-macros --- Cargo.lock | 33 ++- rpc/Cargo.toml | 1 + rpc/src/lib.rs | 2 + rpc/src/v1/helpers/auto_args.rs | 310 --------------------------- rpc/src/v1/helpers/mod.rs | 4 - rpc/src/v1/helpers/params.rs | 46 ---- rpc/src/v1/impls/eth.rs | 2 +- rpc/src/v1/impls/parity.rs | 2 +- rpc/src/v1/impls/parity_set.rs | 2 +- rpc/src/v1/impls/signing.rs | 2 +- rpc/src/v1/impls/signing_unsafe.rs | 2 +- rpc/src/v1/impls/traces.rs | 20 +- rpc/src/v1/traits/eth.rs | 2 +- rpc/src/v1/traits/eth_signing.rs | 3 +- rpc/src/v1/traits/net.rs | 4 +- rpc/src/v1/traits/parity.rs | 6 +- rpc/src/v1/traits/parity_accounts.rs | 3 +- rpc/src/v1/traits/parity_set.rs | 2 +- rpc/src/v1/traits/parity_signing.rs | 2 +- rpc/src/v1/traits/personal.rs | 1 - rpc/src/v1/traits/rpc.rs | 8 +- rpc/src/v1/traits/signer.rs | 2 - rpc/src/v1/traits/traces.rs | 3 +- rpc/src/v1/traits/web3.rs | 2 - 24 files changed, 59 insertions(+), 405 deletions(-) delete mode 100644 rpc/src/v1/helpers/auto_args.rs delete mode 100644 rpc/src/v1/helpers/params.rs diff --git a/Cargo.lock b/Cargo.lock index 9095934c4..6bd3257be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -530,6 +530,7 @@ dependencies = [ "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -860,10 +861,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "4.0.0" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,7 +873,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", @@ -883,7 +884,7 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" version = "0.2.4" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -895,10 +896,19 @@ dependencies = [ "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-macros" +version = "0.1.0" +source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" +dependencies = [ + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-tcp-server" version = "0.1.0" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1295,17 +1305,6 @@ dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.3.5" @@ -2065,6 +2064,7 @@ dependencies = [ "checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" @@ -2107,7 +2107,6 @@ dependencies = [ "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "" -"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6" "checksum parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc5847584161f273e69edc63c1a86254a22f570a0b5dd87aa6f9773f6f7d125" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" "checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 5d974e59f..d766af674 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,6 +15,7 @@ serde_json = "0.8" jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" } ethcore-io = { path = "../util/io" } ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index bbd4a5164..7f105b0d0 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -24,6 +24,8 @@ extern crate serde; extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; +#[macro_use] +extern crate jsonrpc_macros; extern crate ethcore_io as io; extern crate ethcore; diff --git a/rpc/src/v1/helpers/auto_args.rs b/rpc/src/v1/helpers/auto_args.rs deleted file mode 100644 index 9c4e1d74a..000000000 --- a/rpc/src/v1/helpers/auto_args.rs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2015, 2016 Parity Technologies (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 . - -//! Automatically serialize and deserialize parameters around a strongly-typed function. - -// because we reuse the type names as idents in the macros as a dirty hack to -// work around `concat_idents!` being unstable. -#![allow(non_snake_case)] - -use super::errors; - -use jsonrpc_core::{Error, Params, Value, from_params, to_value}; -use serde::{Serialize, Deserialize}; - -/// Auto-generates an RPC trait from trait definition. -/// -/// This just copies out all the methods, docs, and adds another -/// function `to_delegate` which will automatically wrap each strongly-typed -/// function in a wrapper which handles parameter and output type serialization. -/// -/// RPC functions may come in a couple forms: async and synchronous. -/// These are parsed with the custom `#[rpc]` attribute, which must follow -/// documentation. -/// -/// ## The #[rpc] attribute -/// -/// Valid forms: -/// - `#[rpc(name = "name_here")]` (a synchronous rpc function which should be bound to the given name) -/// - `#[rpc(async, name = "name_here")]` (an async rpc function which should be bound to the given name) -/// -/// Synchronous function format: -/// `fn foo(&self, Param1, Param2, Param3) -> Out`. -/// -/// Asynchronous RPC functions must come in this form: -/// `fn foo(&self, Param1, Param2, Param3, Ready); -/// -/// Anything else will be rejected by the code generator. -macro_rules! build_rpc_trait { - // entry-point. todo: make another for traits w/ bounds. - ( - $(#[$t_attr: meta])* - pub trait $name: ident { - $( - $( #[doc=$m_doc:expr] )* - #[ rpc( $($t:tt)* ) ] - fn $m_name: ident ( $($p: tt)* ) $( -> Result<$out: ty, Error> )* ; - )* - } - ) => { - $(#[$t_attr])* - pub trait $name: Sized + Send + Sync + 'static { - $( - $(#[doc=$m_doc])* - fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* ; - )* - - /// Transform this into an `IoDelegate`, automatically wrapping - /// the parameters. - fn to_delegate(self) -> ::jsonrpc_core::IoDelegate { - let mut del = ::jsonrpc_core::IoDelegate::new(self.into()); - $( - build_rpc_trait!(WRAP del => - ( $($t)* ) - fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* - ); - )* - del - } - } - }; - - ( WRAP $del: expr => - (name = $name: expr) - fn $method: ident (&self $(, $param: ty)*) -> Result<$out: ty, Error> - ) => { - $del.add_method($name, move |base, params| { - (Self::$method as fn(&_ $(, $param)*) -> Result<$out, Error>).wrap_rpc(base, params) - }) - }; - - ( WRAP $del: expr => - (async, name = $name: expr) - fn $method: ident (&self, Ready<$out: ty> $(, $param: ty)*) - ) => { - $del.add_async_method($name, move |base, params, ready| { - (Self::$method as fn(&_, Ready<$out> $(, $param)*)).wrap_rpc(base, params, ready) - }) - }; -} - -/// A wrapper type without an implementation of `Deserialize` -/// which allows a special implementation of `Wrap` for functions -/// that take a trailing default parameter. -pub struct Trailing(pub T); - -/// A wrapper type for `jsonrpc_core`'s weakly-typed `Ready` struct. -pub struct Ready { - inner: ::jsonrpc_core::Ready, - _marker: ::std::marker::PhantomData, -} - -impl From<::jsonrpc_core::Ready> for Ready { - fn from(ready: ::jsonrpc_core::Ready) -> Self { - Ready { inner: ready, _marker: ::std::marker::PhantomData } - } -} - -impl Ready { - /// Respond withthe asynchronous result. - pub fn ready(self, result: Result) { - self.inner.ready(result.map(to_value)) - } -} - -/// Wrapper trait for synchronous RPC functions. -pub trait Wrap { - fn wrap_rpc(&self, base: &B, params: Params) -> Result; -} - -/// Wrapper trait for asynchronous RPC functions. -pub trait WrapAsync { - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready); -} - -// special impl for no parameters. -impl Wrap for fn(&B) -> Result - where B: Send + Sync + 'static, OUT: Serialize -{ - fn wrap_rpc(&self, base: &B, params: Params) -> Result { - ::v1::helpers::params::expect_no_params(params) - .and_then(|()| (self)(base)) - .map(to_value) - } -} - -impl WrapAsync for fn(&B, Ready) - where B: Send + Sync + 'static, OUT: Serialize -{ - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { - match ::v1::helpers::params::expect_no_params(params) { - Ok(()) => (self)(base, ready.into()), - Err(e) => ready.ready(Err(e)), - } - } -} - -// creates a wrapper implementation which deserializes the parameters, -// calls the function with concrete type, and serializes the output. -macro_rules! wrap { - ($($x: ident),+) => { - - // synchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - > Wrap for fn(&BASE, $($x,)+) -> Result { - fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { - from_params::<($($x,)+)>(params).and_then(|($($x,)+)| { - (self)(base, $($x,)+) - }).map(to_value) - } - } - - // asynchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - > WrapAsync for fn(&BASE, Ready, $($x,)+ ) { - fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { - match from_params::<($($x,)+)>(params) { - Ok(($($x,)+)) => (self)(base, ready.into(), $($x,)+), - Err(e) => ready.ready(Err(e)), - } - } - } - } -} - -// special impl for no parameters other than block parameter. -impl Wrap for fn(&B, Trailing) -> Result - where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize -{ - fn wrap_rpc(&self, base: &B, params: Params) -> Result { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return Err(errors::invalid_params("not an array", "")), - }; - - let (id,) = match len { - 0 => (T::default(),), - 1 => try!(from_params::<(T,)>(params)), - _ => return Err(Error::invalid_params()), - }; - - (self)(base, Trailing(id)).map(to_value) - } -} - -impl WrapAsync for fn(&B, Ready, Trailing) - where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize -{ - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), - }; - - let id = match len { - 0 => Ok((T::default(),)), - 1 => from_params::<(T,)>(params), - _ => Err(Error::invalid_params()), - }; - - match id { - Ok((id,)) => (self)(base, ready.into(), Trailing(id)), - Err(e) => ready.ready(Err(e)), - } - } -} - -// similar to `wrap!`, but handles a single default trailing parameter -// accepts an additional argument indicating the number of non-trailing parameters. -macro_rules! wrap_with_trailing { - ($num: expr, $($x: ident),+) => { - // synchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - TRAILING: Default + Deserialize, - > Wrap for fn(&BASE, $($x,)+ Trailing) -> Result { - fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return Err(errors::invalid_params("not an array", "")), - }; - - let params = match len - $num { - 0 => from_params::<($($x,)+)>(params) - .map(|($($x,)+)| ($($x,)+ TRAILING::default())), - 1 => from_params::<($($x,)+ TRAILING)>(params) - .map(|($($x,)+ id)| ($($x,)+ id)), - _ => Err(Error::invalid_params()), - }; - - let ($($x,)+ id) = try!(params); - (self)(base, $($x,)+ Trailing(id)).map(to_value) - } - } - - // asynchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - TRAILING: Default + Deserialize, - > WrapAsync for fn(&BASE, Ready, $($x,)+ Trailing) { - fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), - }; - - let params = match len - $num { - 0 => from_params::<($($x,)+)>(params) - .map(|($($x,)+)| ($($x,)+ TRAILING::default())), - 1 => from_params::<($($x,)+ TRAILING)>(params) - .map(|($($x,)+ id)| ($($x,)+ id)), - _ => Err(Error::invalid_params()), - }; - - match params { - Ok(($($x,)+ id)) => (self)(base, ready.into(), $($x,)+ Trailing(id)), - Err(e) => ready.ready(Err(e)) - } - } - } - } -} - -wrap!(A, B, C, D, E); -wrap!(A, B, C, D); -wrap!(A, B, C); -wrap!(A, B); -wrap!(A); - -wrap_with_trailing!(5, A, B, C, D, E); -wrap_with_trailing!(4, A, B, C, D); -wrap_with_trailing!(3, A, B, C); -wrap_with_trailing!(2, A, B); -wrap_with_trailing!(1, A); \ No newline at end of file diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index 3c6d1a739..20ca49ec6 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -14,14 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -#[macro_use] -pub mod auto_args; - #[macro_use] pub mod errors; pub mod dispatch; -pub mod params; pub mod block_import; mod poll_manager; diff --git a/rpc/src/v1/helpers/params.rs b/rpc/src/v1/helpers/params.rs deleted file mode 100644 index b533c1b89..000000000 --- a/rpc/src/v1/helpers/params.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015, 2016 Parity Technologies (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 . - -//! Parameters parsing helpers - -use serde; -use jsonrpc_core::{Error, Params, from_params}; -use v1::types::BlockNumber; -use v1::helpers::errors; - -pub fn expect_no_params(params: Params) -> Result<(), Error> { - match params { - Params::None => Ok(()), - p => Err(errors::invalid_params("No parameters were expected", p)), - } -} - -/// Returns number of different parameters in given `Params` object. -pub fn params_len(params: &Params) -> usize { - match params { - &Params::Array(ref vec) => vec.len(), - _ => 0, - } -} - -/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`. -pub fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize { - match params_len(¶ms) { - 2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)), - _ => from_params::<(F1, F2, BlockNumber)>(params) - } -} - diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 97134951c..1364af033 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -27,6 +27,7 @@ use time::get_time; use ethsync::{SyncProvider}; use ethcore::miner::{MinerService, ExternalMinerService}; use jsonrpc_core::*; +use jsonrpc_macros::Trailing; use util::{H256, Address, FixedHash, U256, H64, Uint}; use util::sha3::*; use util::{FromHex, Mutex}; @@ -51,7 +52,6 @@ use v1::types::{ use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; use v1::helpers::dispatch::{dispatch_transaction, default_gas_price}; use v1::helpers::block_import::is_major_importing; -use v1::helpers::auto_args::Trailing; const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 1f995749a..2c6a498a1 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -32,6 +32,7 @@ use ethcore::mode::Mode; use ethcore::account_provider::AccountProvider; use jsonrpc_core::Error; +use jsonrpc_macros::Trailing; use v1::traits::Parity; use v1::types::{ Bytes, U256, H160, H256, H512, @@ -41,7 +42,6 @@ use v1::types::{ }; use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::dispatch::DEFAULT_MAC; -use v1::helpers::auto_args::Trailing; /// Parity implementation. pub struct ParityClient where diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index b63adaa67..6371a46ea 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -26,7 +26,7 @@ use fetch::{Client as FetchClient, Fetch}; use util::{Mutex, sha3}; use jsonrpc_core::Error; -use v1::helpers::auto_args::Ready; +use jsonrpc_macros::Ready; use v1::helpers::errors; use v1::traits::ParitySet; use v1::types::{Bytes, H160, H256, U256}; diff --git a/rpc/src/v1/impls/signing.rs b/rpc/src/v1/impls/signing.rs index 5fc6558da..c65e30816 100644 --- a/rpc/src/v1/impls/signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -25,7 +25,7 @@ use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; use jsonrpc_core::Error; -use v1::helpers::auto_args::Ready; +use jsonrpc_macros::Ready; use v1::helpers::{ errors, dispatch, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs index 2b3b81d57..17dbdcb55 100644 --- a/rpc/src/v1/impls/signing_unsafe.rs +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -24,7 +24,7 @@ use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; use jsonrpc_core::Error; -use v1::helpers::auto_args::Ready; +use jsonrpc_macros::Ready; use v1::helpers::errors; use v1::helpers::dispatch; use v1::traits::{EthSigning, ParitySigning}; diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 2fd912284..6b37e40cc 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -18,13 +18,15 @@ use std::sync::{Weak, Arc}; use jsonrpc_core::*; +use serde; + use rlp::{UntrustedRlp, View}; use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId}; use ethcore::miner::MinerService; use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; + use v1::traits::Traces; use v1::helpers::{errors, CallRequest as CRequest}; -use v1::helpers::params::from_params_default_third; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; fn to_call_analytics(flags: Vec) -> CallAnalytics { @@ -35,6 +37,22 @@ fn to_call_analytics(flags: Vec) -> CallAnalytics { } } +/// Returns number of different parameters in given `Params` object. +fn params_len(params: &Params) -> usize { + match params { + &Params::Array(ref vec) => vec.len(), + _ => 0, + } +} + +/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`. +fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize { + match params_len(¶ms) { + 2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)), + _ => from_params::<(F1, F2, BlockNumber)>(params) + } +} + /// Traces api implementation. pub struct TracesClient where C: BlockChainClient, M: MinerService { client: Weak, diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 14ee8ca62..2d52b7c70 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -21,7 +21,7 @@ use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChange use v1::types::{Log, Receipt, SyncStatus, Transaction, Work}; use v1::types::{H64, H160, H256, U256}; -use v1::helpers::auto_args::{Trailing, Wrap}; +use jsonrpc_macros::Trailing; build_rpc_trait! { /// Eth rpc interface. diff --git a/rpc/src/v1/traits/eth_signing.rs b/rpc/src/v1/traits/eth_signing.rs index aa306f3f0..442883339 100644 --- a/rpc/src/v1/traits/eth_signing.rs +++ b/rpc/src/v1/traits/eth_signing.rs @@ -16,7 +16,8 @@ //! Eth rpc interface. -use v1::helpers::auto_args::{WrapAsync, Ready}; +use jsonrpc_macros::Ready; + use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index a34270826..ebe93472e 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -17,8 +17,6 @@ //! Net rpc interface. use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; - build_rpc_trait! { /// Net rpc interface. pub trait Net { @@ -35,4 +33,4 @@ build_rpc_trait! { #[rpc(name = "net_listening")] fn is_listening(&self) -> Result; } -} \ No newline at end of file +} diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index ba6514168..fecc05667 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -15,10 +15,12 @@ // along with Parity. If not, see . //! Parity-specific rpc interface. -use jsonrpc_core::Error; use std::collections::BTreeMap; -use v1::helpers::auto_args::{Wrap, Trailing}; + +use jsonrpc_core::Error; +use jsonrpc_macros::Trailing; + use v1::types::{ H160, H256, H512, U256, Bytes, Peers, Transaction, RpcSettings, Histogram, diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index e4393c149..d21a8459e 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -16,9 +16,8 @@ //! Parity Accounts-related rpc interface. use std::collections::BTreeMap; -use jsonrpc_core::{Value, Error}; -use v1::helpers::auto_args::Wrap; +use jsonrpc_core::{Value, Error}; use v1::types::{H160, H256, DappId}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index 486f7fb42..6ae3610c8 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -17,8 +17,8 @@ //! Parity-specific rpc interface for operations altering the settings. use jsonrpc_core::Error; +use jsonrpc_macros::Ready; -use v1::helpers::auto_args::{Wrap, WrapAsync, Ready}; use v1::types::{Bytes, H160, H256, U256}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/parity_signing.rs b/rpc/src/v1/traits/parity_signing.rs index 5eb5ff8b3..a6fdbe2cd 100644 --- a/rpc/src/v1/traits/parity_signing.rs +++ b/rpc/src/v1/traits/parity_signing.rs @@ -16,8 +16,8 @@ //! ParitySigning rpc interface. use jsonrpc_core::Error; +use jsonrpc_macros::Ready; -use v1::helpers::auto_args::{Wrap, WrapAsync, Ready}; use v1::types::{U256, H160, H256, Bytes, ConfirmationResponse, TransactionRequest, Either}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index edb1a9d79..a7cc996ea 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -17,7 +17,6 @@ //! Personal rpc interface. use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; use v1::types::{U128, H160, H256, TransactionRequest}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/rpc.rs b/rpc/src/v1/traits/rpc.rs index a03d67b55..9b44b560f 100644 --- a/rpc/src/v1/traits/rpc.rs +++ b/rpc/src/v1/traits/rpc.rs @@ -16,12 +16,10 @@ //! RPC interface. -use jsonrpc_core::Error; - -use v1::helpers::auto_args::Wrap; - use std::collections::BTreeMap; +use jsonrpc_core::Error; + build_rpc_trait! { /// RPC Interface. pub trait Rpc { @@ -33,4 +31,4 @@ build_rpc_trait! { #[rpc(name = "rpc_modules")] fn rpc_modules(&self) -> Result, Error>; } -} \ No newline at end of file +} diff --git a/rpc/src/v1/traits/signer.rs b/rpc/src/v1/traits/signer.rs index 5a18fe293..19861b922 100644 --- a/rpc/src/v1/traits/signer.rs +++ b/rpc/src/v1/traits/signer.rs @@ -17,10 +17,8 @@ //! Parity Signer-related rpc interface. use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; use v1::types::{U256, Bytes, TransactionModification, ConfirmationRequest, ConfirmationResponse}; - build_rpc_trait! { /// Signer extension for confirmations rpc interface. pub trait Signer { diff --git a/rpc/src/v1/traits/traces.rs b/rpc/src/v1/traits/traces.rs index 0440b4dff..36561216f 100644 --- a/rpc/src/v1/traits/traces.rs +++ b/rpc/src/v1/traits/traces.rs @@ -15,8 +15,9 @@ // along with Parity. If not, see . //! Traces specific rpc interface. + use std::sync::Arc; -use jsonrpc_core::*; +use jsonrpc_core::{Params, Value, Error, IoDelegate}; /// Traces specific rpc interface. pub trait Traces: Sized + Send + Sync + 'static { diff --git a/rpc/src/v1/traits/web3.rs b/rpc/src/v1/traits/web3.rs index efe26e307..c2f5f55e1 100644 --- a/rpc/src/v1/traits/web3.rs +++ b/rpc/src/v1/traits/web3.rs @@ -17,10 +17,8 @@ //! Web3 rpc interface. use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; use v1::types::{H256, Bytes}; - build_rpc_trait! { /// Web3 rpc interface. pub trait Web3 { From 65d62ccf04d29e03465779937be6b2dc6f5acfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Dec 2016 14:59:19 +0100 Subject: [PATCH 31/32] Altering the order [ci:skip] --- rpc/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 7f105b0d0..c5af5d727 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -24,8 +24,6 @@ extern crate serde; extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; -#[macro_use] -extern crate jsonrpc_macros; extern crate ethcore_io as io; extern crate ethcore; @@ -44,6 +42,8 @@ extern crate fetch; extern crate log; #[macro_use] extern crate ethcore_util as util; +#[macro_use] +extern crate jsonrpc_macros; #[cfg(test)] extern crate ethjson; From 1a9a142a69aa18c38afb878090386dc54b623189 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 13 Dec 2016 17:19:48 +0000 Subject: [PATCH 32/32] [ci skip] js-precompiled 20161213-171715 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bd3257be..e76a6749b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#a8f4db707c521f71f093b62e3173b98144569c4e" +source = "git+https://github.com/ethcore/js-precompiled.git#175003ae159b126302fd1a90dd875dc86d7adba0" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 36cd9ad5a..8581c9cb6 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.121", + "version": "0.2.122", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ",