diff --git a/Cargo.lock b/Cargo.lock index f47d5d5cdcc..dc7bf8a507f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,7 @@ version = "0.1.2" dependencies = [ "bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/dapps/src/handlers/fetch.rs b/dapps/src/handlers/fetch.rs index 7634f194108..c3e66873355 100644 --- a/dapps/src/handlers/fetch.rs +++ b/dapps/src/handlers/fetch.rs @@ -34,7 +34,7 @@ use endpoint::EndpointPath; use handlers::{ContentHandler, StreamingHandler}; use page::{LocalPageEndpoint, PageHandlerWaiting}; -const FETCH_TIMEOUT: u64 = 30; +const FETCH_TIMEOUT: u64 = 300; pub enum ValidatorResponse { Local(LocalPageEndpoint), diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 906e1c90c5e..ddd435fd258 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -24,7 +24,9 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x3" + "networkID" : "0x3", + "forkBlock": 333922, + "forkCanonHash": "0x8737eb141d4f05db57af63fc8d3b4d4d8f9cddb0c4e1ab855de8c288fdc1924f" }, "genesis": { "seal": { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index befe73ca89f..8785e43c053 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -908,7 +908,7 @@ impl BlockChainClient for Client { Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm) .transact(&tx, options.clone()) - .map(|r| r.exception.is_some()) + .map(|r| r.exception.is_none()) .unwrap_or(false) }; diff --git a/js/package.json b/js/package.json index 7e43c37fd7d..c2ed1b21a1e 100644 --- a/js/package.json +++ b/js/package.json @@ -189,6 +189,7 @@ "valid-url": "1.0.9", "validator": "6.2.0", "web3": "0.17.0-beta", - "whatwg-fetch": "2.0.1" + "whatwg-fetch": "2.0.1", + "zxcvbn": "4.4.1" } } diff --git a/js/src/3rdparty/email-verification/index.js b/js/src/3rdparty/email-verification/index.js index ca1b0413812..d49ba31971f 100644 --- a/js/src/3rdparty/email-verification/index.js +++ b/js/src/3rdparty/email-verification/index.js @@ -16,6 +16,19 @@ import { stringify } from 'querystring'; +export const isServerRunning = (isTestnet = false) => { + const port = isTestnet ? 28443 : 18443; + return fetch(`https://email-verification.parity.io:${port}/health`, { + mode: 'cors', cache: 'no-store' + }) + .then((res) => { + return res.ok; + }) + .catch(() => { + return false; + }); +}; + export const postToServer = (query, isTestnet = false) => { const port = isTestnet ? 28443 : 18443; query = stringify(query); diff --git a/js/src/3rdparty/sms-verification/index.js b/js/src/3rdparty/sms-verification/index.js index 23e978972ec..ed890631f95 100644 --- a/js/src/3rdparty/sms-verification/index.js +++ b/js/src/3rdparty/sms-verification/index.js @@ -16,6 +16,19 @@ import { stringify } from 'querystring'; +export const isServerRunning = (isTestnet = false) => { + const port = isTestnet ? 8443 : 443; + return fetch(`https://sms-verification.parity.io:${port}/health`, { + mode: 'cors', cache: 'no-store' + }) + .then((res) => { + return res.ok; + }) + .catch(() => { + return false; + }); +}; + export const postToServer = (query, isTestnet = false) => { const port = isTestnet ? 8443 : 443; query = stringify(query); diff --git a/js/src/dapps/index.js b/js/src/dapps/index.js index 584fbb319bc..32e2ececd26 100644 --- a/js/src/dapps/index.js +++ b/js/src/dapps/index.js @@ -16,7 +16,7 @@ module.exports = [ { name: 'basiccoin', entry: 'basiccoin.js', title: 'Basic Token Deployment' }, - { name: 'dappreg', entry: 'dappreg.js', title: 'Dapp Registry' }, + { name: 'dappreg', entry: 'dappreg.js', title: 'Dapp Registry', secure: true }, { name: 'githubhint', entry: 'githubhint.js', title: 'GitHub Hint', secure: true }, { name: 'localtx', entry: 'localtx.js', title: 'Local transactions Viewer', secure: true }, { name: 'registry', entry: 'registry.js', title: 'Registry' }, diff --git a/js/src/modals/CreateAccount/NewAccount/newAccount.js b/js/src/modals/CreateAccount/NewAccount/newAccount.js index ed2c24612a6..cbf7d158716 100644 --- a/js/src/modals/CreateAccount/NewAccount/newAccount.js +++ b/js/src/modals/CreateAccount/NewAccount/newAccount.js @@ -15,7 +15,7 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; -import IconButton from 'material-ui/IconButton'; +import { IconButton } from 'material-ui'; import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'; import ActionAutorenew from 'material-ui/svg-icons/action/autorenew'; diff --git a/js/src/modals/CreateAccount/RecoveryPhrase/recoveryPhrase.js b/js/src/modals/CreateAccount/RecoveryPhrase/recoveryPhrase.js index dc80e27ae43..9d76cebfaaf 100644 --- a/js/src/modals/CreateAccount/RecoveryPhrase/recoveryPhrase.js +++ b/js/src/modals/CreateAccount/RecoveryPhrase/recoveryPhrase.js @@ -88,12 +88,13 @@ export default class RecoveryPhrase extends Component { value={ password2 } onChange={ this.onEditPassword2 } /> - + ); } diff --git a/js/src/modals/CreateAccount/createAccount.js b/js/src/modals/CreateAccount/createAccount.js index 53be1f91839..e1e6abc7192 100644 --- a/js/src/modals/CreateAccount/createAccount.js +++ b/js/src/modals/CreateAccount/createAccount.js @@ -16,6 +16,7 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; + import ActionDone from 'material-ui/svg-icons/action/done'; import ActionDoneAll from 'material-ui/svg-icons/action/done-all'; import ContentClear from 'material-ui/svg-icons/content/clear'; @@ -100,44 +101,45 @@ export default class CreateAccount extends Component { switch (stage) { case 0: return ( - + ); case 1: if (createType === 'fromNew') { return ( - + ); - } else if (createType === 'fromGeth') { + } + + if (createType === 'fromGeth') { return ( + onChange={ this.onChangeGeth } + /> ); - } else if (createType === 'fromPhrase') { + } + + if (createType === 'fromPhrase') { return ( - + ); - } else if (createType === 'fromRaw') { + } + + if (createType === 'fromRaw') { return ( - + ); } return ( - + ); case 2: if (createType === 'fromGeth') { return ( - + ); } @@ -145,7 +147,8 @@ export default class CreateAccount extends Component { + phrase={ this.state.phrase } + /> ); } } @@ -210,11 +213,14 @@ export default class CreateAccount extends Component { } return ( - - } /> + + } + /> ); } @@ -371,7 +377,7 @@ export default class CreateAccount extends Component { } onChangeDetails = (canCreate, { name, passwordHint, address, password, phrase, rawKey, windowsPhrase }) => { - this.setState({ + const nextState = { canCreate, name, passwordHint, @@ -380,7 +386,9 @@ export default class CreateAccount extends Component { phrase, windowsPhrase: windowsPhrase || false, rawKey - }); + }; + + this.setState(nextState); } onChangeRaw = (canCreate, rawKey) => { diff --git a/js/src/modals/PasswordManager/passwordManager.js b/js/src/modals/PasswordManager/passwordManager.js index a1d3f5be36d..1bd3ea91c89 100644 --- a/js/src/modals/PasswordManager/passwordManager.js +++ b/js/src/modals/PasswordManager/passwordManager.js @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { newError, openSnackbar } from '~/redux/actions'; -import { Button, Modal, IdentityName, IdentityIcon } from '~/ui'; +import { Button, Modal, IdentityName, IdentityIcon, PasswordStrength } from '~/ui'; import Form, { Input } from '~/ui/Form'; import { CancelIcon, CheckIcon, SendIcon } from '~/ui/Icons'; @@ -120,7 +120,7 @@ class PasswordManager extends Component { } renderPage () { - const { busy, isRepeatValid, passwordHint } = this.store; + const { busy, isRepeatValid, newPassword, passwordHint } = this.store; return ( + + diff --git a/js/src/modals/Transfer/store.js b/js/src/modals/Transfer/store.js index 9da9023f1a3..63a29c9a15a 100644 --- a/js/src/modals/Transfer/store.js +++ b/js/src/modals/Transfer/store.js @@ -220,13 +220,27 @@ export default class TransferStore { } @action _attachWalletOperation = (txhash) => { + if (!txhash || /^(0x)?0*$/.test(txhash)) { + return; + } + let ethSubscriptionId = null; + // Number of blocks left to look-up (unsub after 15 blocks if nothing) + let nBlocksLeft = 15; + return this.api.subscribe('eth_blockNumber', () => { this.api.eth .getTransactionReceipt(txhash) .then((tx) => { + if (nBlocksLeft <= 0) { + this.api.unsubscribe(ethSubscriptionId); + ethSubscriptionId = null; + return; + } + if (!tx) { + nBlocksLeft--; return; } @@ -239,6 +253,10 @@ export default class TransferStore { this.operation = operations[0]; } + this.api.unsubscribe(ethSubscriptionId); + ethSubscriptionId = null; + }) + .catch(() => { this.api.unsubscribe(ethSubscriptionId); ethSubscriptionId = null; }); diff --git a/js/src/modals/Verification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js index 57386ed2086..888585fccbc 100644 --- a/js/src/modals/Verification/GatherData/gatherData.js +++ b/js/src/modals/Verification/GatherData/gatherData.js @@ -15,6 +15,7 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import { FormattedMessage } from 'react-intl'; import BigNumber from 'bignumber.js'; import { Checkbox } from 'material-ui'; import InfoIcon from 'material-ui/svg-icons/action/info-outline'; @@ -33,10 +34,11 @@ import styles from './gatherData.css'; export default class GatherData extends Component { static propTypes = { fee: React.PropTypes.instanceOf(BigNumber), - method: PropTypes.string.isRequired, fields: PropTypes.array.isRequired, - isVerified: nullableProptype(PropTypes.bool.isRequired), hasRequested: nullableProptype(PropTypes.bool.isRequired), + isServerRunning: nullableProptype(PropTypes.bool.isRequired), + isVerified: nullableProptype(PropTypes.bool.isRequired), + method: PropTypes.string.isRequired, setConsentGiven: PropTypes.func.isRequired } @@ -48,13 +50,19 @@ export default class GatherData extends Component { return (
{ howItWorks } + { this.renderServerRunning() } { this.renderFee() } { this.renderCertified() } { this.renderRequested() } { this.renderFields() } + } disabled={ isVerified } onCheck={ this.consentOnChange } /> @@ -63,6 +71,44 @@ export default class GatherData extends Component { ); } + renderServerRunning () { + const { isServerRunning } = this.props; + + if (isServerRunning) { + return ( +
+ +

+ +

+
+ ); + } else if (isServerRunning === false) { + return ( +
+ +

+ +

+
+ ); + } + return ( +

+ +

+ ); + } + renderFee () { const { fee } = this.props; @@ -72,7 +118,15 @@ export default class GatherData extends Component { return (
-

The fee is { fromWei(fee).toFixed(3) } ETH.

+

+ +

); } @@ -84,19 +138,34 @@ export default class GatherData extends Component { return (
-

Your account is already verified.

+

+ +

); } else if (isVerified === false) { return (
-

Your account is not verified yet.

+

+ +

); } return ( -

Checking if your account is verified…

+

+ +

); } @@ -112,19 +181,34 @@ export default class GatherData extends Component { return (
-

You already requested verification.

+

+ +

); } else if (hasRequested === false) { return (
-

You did not request verification yet.

+

+ +

); } return ( -

Checking if you requested verification…

+

+ +

); } diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js index 5360ad61110..07a6baaad28 100644 --- a/js/src/modals/Verification/email-store.js +++ b/js/src/modals/Verification/email-store.js @@ -21,7 +21,7 @@ import EmailVerificationABI from '~/contracts/abi/email-verification.json'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; -import { postToServer } from '../../3rdparty/email-verification'; +import { isServerRunning, postToServer } from '../../3rdparty/email-verification'; const EMAIL_VERIFICATION = 7; // id in the `BadgeReg.sol` contract @@ -59,6 +59,10 @@ export default class EmailVerificationStore extends VerificationStore { super(api, EmailVerificationABI, EMAIL_VERIFICATION, account, isTestnet); } + isServerRunning = () => { + return isServerRunning(this.isTestnet); + } + requestValues = () => [ sha3.text(this.email) ] @action setEmail = (email) => { diff --git a/js/src/modals/Verification/sms-store.js b/js/src/modals/Verification/sms-store.js index 7b1b859db6d..3aa338ef28c 100644 --- a/js/src/modals/Verification/sms-store.js +++ b/js/src/modals/Verification/sms-store.js @@ -21,7 +21,7 @@ import SMSVerificationABI from '~/contracts/abi/sms-verification.json'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; -import { postToServer } from '../../3rdparty/sms-verification'; +import { isServerRunning, postToServer } from '../../3rdparty/sms-verification'; const SMS_VERIFICATION = 0; // id in the `BadgeReg.sol` contract @@ -58,6 +58,10 @@ export default class SMSVerificationStore extends VerificationStore { super(api, SMSVerificationABI, SMS_VERIFICATION, account, isTestnet); } + isServerRunning = () => { + return isServerRunning(this.isTestnet); + } + @action setNumber = (number) => { this.number = number; } diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index 06250fd76d9..eeec7178823 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -40,6 +40,7 @@ export default class VerificationStore { @observable fee = null; @observable isVerified = null; @observable hasRequested = null; + @observable isServerRunning = null; @observable consentGiven = false; @observable requestTx = null; @observable code = ''; @@ -73,6 +74,14 @@ export default class VerificationStore { const { contract, account } = this; this.step = LOADING; + const isServerRunning = this.isServerRunning() + .then((isRunning) => { + this.isServerRunning = isRunning; + }) + .catch((err) => { + this.error = 'Failed to check if server is running: ' + err.message; + }); + const fee = contract.instance.fee.call() .then((fee) => { this.fee = fee; @@ -101,7 +110,7 @@ export default class VerificationStore { }); Promise - .all([ fee, isVerified, hasRequested ]) + .all([ isServerRunning, fee, isVerified, hasRequested ]) .then(() => { this.step = QUERY_DATA; }); diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js index 0fac3bf755c..e6e32d148ac 100644 --- a/js/src/modals/Verification/verification.js +++ b/js/src/modals/Verification/verification.js @@ -94,10 +94,10 @@ class Verification extends Component { return ( { this.renderStep(phase, error) } @@ -111,8 +111,9 @@ class Verification extends Component { const cancel = (