Merge branch 'master' into jg-signer-api-queries-2

This commit is contained in:
Jaco Greeff 2016-11-22 09:49:17 +01:00
commit a475c2166c
26 changed files with 394 additions and 356 deletions

2
Cargo.lock generated
View File

@ -1263,7 +1263,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#587684374a12bf715151dd987a552a3d61e42972"
source = "git+https://github.com/ethcore/js-precompiled.git#f46188126257e03c775e76a3cea82b5f70549400"
dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -21,8 +21,8 @@
"genesis": {
"seal": {
"generic": {
"fields": 1,
"rlp": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
"fields": 2,
"rlp": "0x200"
}
},
"difficulty": "0x20000",

View File

@ -8,7 +8,7 @@
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
"registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
"homesteadTransition": 0,
"eip150Transition": 0,
"eip155Transition": 10,

View File

@ -11,9 +11,9 @@
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x00006d6f7264656e",
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
"generic": {
"fields": 0,
"rlp": "0x0"
}
},
"difficulty": "0x20000",

View File

@ -417,13 +417,13 @@ mod tests {
let engine = Spec::new_test_round().engine;
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
let mut step = UNIX_EPOCH.elapsed().unwrap().as_secs();
let time = UNIX_EPOCH.elapsed().unwrap().as_secs();
// Two authorities.
let mut step = time - time % 2;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let first_ok = engine.verify_block_seal(&header).is_ok();
assert!(engine.verify_block_seal(&header).is_err());
step = step + 1;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let second_ok = engine.verify_block_seal(&header).is_ok();
assert!(first_ok ^ second_ok);
assert!(engine.verify_block_seal(&header).is_ok());
}
}

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "0.2.58",
"version": "0.2.61",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",

View File

@ -14,9 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { stringify } from 'querystring';
import React from 'react';
export default (
export const termsOfService = (
<ul>
<li>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.</li>
<li>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.</li>
@ -25,3 +26,18 @@ export default (
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
</ul>
);
export const postToServer = (query) => {
query = stringify(query);
return fetch('https://sms-verification.parity.io/?' + 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');
});
});
};

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { stringify } from 'querystring';
export const checkIfVerified = (contract, account) => {
return contract.instance.certified.call({}, [account]);
};
@ -35,18 +33,3 @@ export const checkIfRequested = (contract, account) => {
});
});
};
export const postToServer = (query) => {
query = stringify(query);
return fetch('https://sms-verification.parity.io/?' + 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');
});
});
};

View File

@ -77,7 +77,7 @@ export default class Lookup extends Component {
label='Lookup'
primary
icon={ <SearchIcon /> }
onClick={ this.onLookupClick }
onTouchTap={ this.onLookupClick }
/>
</div>
<CardText>{ output }</CardText>

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { sha3 } from '../parity.js';
import { sha3, api } from '../parity.js';
const alreadyQueued = (queue, action, name) =>
!!queue.find((entry) => entry.action === action && entry.name === name);
@ -43,14 +43,23 @@ export const reserve = (name) => (dispatch, getState) => {
const values = [ sha3(name) ];
dispatch(reserveStart(name));
reserve.estimateGas(options, values)
.then((gas) => {
options.gas = gas.mul(1.2).toFixed(0);
return reserve.postTransaction(options, values);
})
.then((data) => {
.then((requestId) => {
return api.pollMethod('parity_checkRequest', requestId);
})
.then((txhash) => {
dispatch(reserveSuccess(name));
}).catch((err) => {
})
.catch((err) => {
if (err && err.type === 'REQUEST_REJECTED') {
return dispatch(reserveFail(name));
}
console.error(`could not reserve ${name}`);
if (err) console.error(err.stack);
dispatch(reserveFail(name));
@ -81,9 +90,17 @@ export const drop = (name) => (dispatch, getState) => {
options.gas = gas.mul(1.2).toFixed(0);
return drop.postTransaction(options, values);
})
.then((data) => {
.then((requestId) => {
return api.pollMethod('parity_checkRequest', requestId);
})
.then((txhash) => {
dispatch(dropSuccess(name));
}).catch((err) => {
})
.catch((err) => {
if (err && err.type === 'REQUEST_REJECTED') {
dispatch(reserveFail(name));
}
console.error(`could not drop ${name}`);
if (err) console.error(err.stack);
dispatch(reserveFail(name));

View File

@ -86,6 +86,22 @@ export default class Names extends Component {
name: ''
};
componentWillReceiveProps (nextProps) {
const nextQueue = nextProps.queue;
const prevQueue = this.props.queue;
if (nextQueue.length > prevQueue.length) {
const newQueued = nextQueue[nextQueue.length - 1];
const newName = newQueued.name;
if (newName !== this.state.name) {
return;
}
this.setState({ name: '' });
}
}
render () {
const { action, name } = this.state;
const { fee, pending, queue } = this.props;
@ -120,7 +136,7 @@ export default class Names extends Component {
label={ action === 'reserve' ? 'Reserve' : 'Drop' }
primary
icon={ <CheckIcon /> }
onClick={ this.onSubmitClick }
onTouchTap={ this.onSubmitClick }
/>
{ queue.length > 0
? (<div>{ useSignerText }{ renderQueue(queue) }</div>)

View File

@ -52,7 +52,7 @@ export default class Records extends Component {
label='Save'
primary
icon={ <SaveIcon /> }
onClick={ this.onSaveClick }
onTouchTap={ this.onSaveClick }
/>
</CardText>
</Card>

View File

@ -174,7 +174,7 @@ export default class LoadContract extends Component {
const secondaryText = description || `Saved ${moment(timestamp).fromNow()}`;
const remove = removable
? (
<IconButton onClick={ onDelete }>
<IconButton onTouchTap={ onDelete }>
<DeleteIcon />
</IconButton>
)

View File

@ -25,7 +25,7 @@ import ErrorIcon from 'material-ui/svg-icons/navigation/close';
import { fromWei } from '../../../api/util/wei';
import { Form, Input } from '../../../ui';
import terms from '../terms-of-service';
import { termsOfService } from '../../../3rdparty/sms-verification';
import styles from './gatherData.css';
export default class GatherData extends Component {
@ -66,7 +66,7 @@ export default class GatherData extends Component {
disabled={ isVerified }
onCheck={ this.consentOnChange }
/>
<div className={ styles.terms }>{ terms }</div>
<div className={ styles.terms }>{ termsOfService }</div>
</Form>
);
}
@ -123,8 +123,7 @@ export default class GatherData extends Component {
<p className={ styles.message }>You already requested verification.</p>
</div>
);
}
if (hasRequested === false) {
} else if (hasRequested === false) {
return (
<div className={ styles.container }>
<SuccessIcon />

View File

@ -16,8 +16,8 @@
import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react';
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
import ContentClear from 'material-ui/svg-icons/content/clear';
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';
@ -77,7 +77,7 @@ export default class SMSVerification extends Component {
const cancel = (
<Button
key='cancel' label='Cancel'
icon={ <ContentClear /> }
icon={ <CancelIcon /> }
onClick={ onClose }
/>
);
@ -92,7 +92,7 @@ export default class SMSVerification extends Component {
<Button
key='done' label='Done'
disabled={ !isStepValid }
icon={ <ActionDoneAll /> }
icon={ <DoneIcon /> }
onClick={ onClose }
/>
</div>
@ -140,24 +140,13 @@ export default class SMSVerification extends Component {
setNumber, setConsentGiven, setCode
} = this.props.store;
if (phase === 5) {
return (<Done />);
}
if (phase === 4) {
return (<SendConfirmation step={ step } tx={ confirmationTx } />);
}
if (phase === 3) {
switch (phase) {
case 0:
return (
<QueryCode
number={ number } fee={ fee } isCodeValid={ isCodeValid }
setCode={ setCode }
/>
<p>Loading SMS Verification.</p>
);
}
if (phase === 2) {
return (<SendRequest step={ step } tx={ requestTx } />);
}
if (phase === 1) {
case 1:
const { setNumber, setConsentGiven } = this.props.store;
return (
<GatherData
@ -166,11 +155,32 @@ export default class SMSVerification extends Component {
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
/>
);
}
if (phase === 0) {
return (<p>Preparing awesomeness!</p>);
}
case 2:
return (
<SendRequest step={ step } tx={ requestTx } />
);
case 3:
return (
<QueryCode
number={ number } fee={ fee } isCodeValid={ isCodeValid }
setCode={ setCode }
/>
);
case 4:
return (
<SendConfirmation step={ step } tx={ confirmationTx } />
);
case 5:
return (
<Done />
);
default:
return null;
}
}
}

View File

@ -20,7 +20,8 @@ import { sha3 } from '../../api/util/sha3';
import Contracts from '../../contracts';
import { checkIfVerified, checkIfRequested, postToServer } from '../../contracts/sms-verification';
import { checkIfVerified, checkIfRequested } from '../../contracts/sms-verification';
import { postToServer } from '../../3rdparty/sms-verification';
import checkIfTxFailed from '../../util/check-if-tx-failed';
import waitForConfirmations from '../../util/wait-for-block-confirmations';
@ -87,7 +88,7 @@ export default class VerificationStore {
this.account = account;
this.step = LOADING;
Contracts.create(api).registry.getContract('smsVerification')
Contracts.create(api).registry.getContract('smsverification')
.then((contract) => {
this.contract = contract;
this.load();

View File

@ -155,24 +155,20 @@ export default class Status {
const { refreshStatus } = this._store.getState().nodeStatus;
const statusPromises = [ this._api.eth.syncing() ];
const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ];
if (refreshStatus) {
statusPromises.push(this._api.eth.hashrate());
statusPromises.push(this._api.parity.netPeers());
}
Promise
.all(statusPromises)
.then((statusResults) => {
const status = statusResults.length === 1
? {
syncing: statusResults[0]
}
.then(([ syncing, netPeers, ...statusResults ]) => {
const status = statusResults.length === 0
? { syncing, netPeers }
: {
syncing: statusResults[0],
hashrate: statusResults[1],
netPeers: statusResults[2]
syncing, netPeers,
hashrate: statusResults[0]
};
if (!isEqual(status, this._status)) {

View File

@ -96,7 +96,7 @@ export default class TypedInput extends Component {
<IconButton
iconStyle={ iconStyle }
style={ style }
onClick={ this.onAddField }
onTouchTap={ this.onAddField }
>
<AddIcon />
</IconButton>
@ -104,7 +104,7 @@ export default class TypedInput extends Component {
<IconButton
iconStyle={ iconStyle }
style={ style }
onClick={ this.onRemoveField }
onTouchTap={ this.onRemoveField }
>
<RemoveIcon />
</IconButton>

View File

@ -67,7 +67,7 @@ export default class Dapps extends Component {
label='edit'
key='edit'
icon={ <EyeIcon /> }
onClick={ this.store.openModal }
onTouchTap={ this.store.openModal }
/>
] }
/>

View File

@ -74,7 +74,7 @@ class TransactionPendingFormConfirm extends Component {
data-effect='solid'
>
<RaisedButton
onClick={ this.onConfirm }
onTouchTap={ this.onConfirm }
className={ styles.confirmButton }
fullWidth
primary

View File

@ -37,7 +37,7 @@ export default class TransactionPendingFormReject extends Component {
<strong>This cannot be undone</strong>
</div>
<RaisedButton
onClick={ onReject }
onTouchTap={ onReject }
className={ styles.rejectButton }
fullWidth
label={ 'Reject Transaction' }

View File

@ -57,7 +57,7 @@ export default class CallsToolbar extends Component {
<div className={ styles.callActions } { ...this._test('button-container') }>
<IconButton
className={ styles.callAction }
onClick={ this.setCall }
onTouchTap={ this.setCall }
tooltip='Set'
tooltipPosition='top-left'
{ ...this._test('button-setCall') }
@ -66,7 +66,7 @@ export default class CallsToolbar extends Component {
</IconButton>
<IconButton
className={ styles.callAction }
onClick={ this.makeCall }
onTouchTap={ this.makeCall }
tooltip='Fire again'
tooltipPosition='top-left'
{ ...this._test('button-makeCall') }

View File

@ -45,7 +45,7 @@ export default class ScrollTopButton extends Component {
return (
<IconButton
className={ `${styles.scrollButton} ${hiddenClass}` }
onClick={ this._scrollToTop }>
onTouchTap={ this._scrollToTop }>
<ArrowUpwardIcon />
</IconButton>
);

View File

@ -102,7 +102,7 @@ fn import(i: ImportAccounts) -> Result<String, String> {
let from = DiskDirectory::at(path);
imported += try!(import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")).len();
}
Ok(format!("{}", imported))
Ok(format!("{} account(s) imported", imported))
}
fn import_geth(i: ImportFromGethAccounts) -> Result<String, String> {

View File

@ -32,7 +32,7 @@ Operating Options:
(default: {flag_mode_alarm}).
--chain CHAIN Specify the blockchain type. CHAIN may be either a
JSON chain specification file or olympic, frontier,
homestead, mainnet, morden, classic, expanse,
homestead, mainnet, morden, ropsten, classic, expanse,
testnet or dev (default: {flag_chain}).
-d --db-path PATH Specify the database & configuration directory path
(default: {flag_db_path}).

View File

@ -313,7 +313,7 @@ impl Configuration {
fn chain(&self) -> String {
if self.args.flag_testnet {
"morden".to_owned()
"ropsten".to_owned()
} else {
self.args.flag_chain.clone()
}
@ -905,7 +905,7 @@ mod tests {
// then
assert_eq!(conf.network_settings(), NetworkSettings {
name: "testname".to_owned(),
chain: "morden".to_owned(),
chain: "ropsten".to_owned(),
network_port: 30303,
rpc_enabled: true,
rpc_interface: "local".to_owned(),