diff --git a/Cargo.lock b/Cargo.lock index a19426640..7b3a3d3cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1250,7 +1250,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#5e3b9629692c550811b228d68ca99d1461a4f6cb" +source = "git+https://github.com/ethcore/js-precompiled.git#957c5a66c33f3b06a7ae804ac5edc59c20e4535b" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index 97066e40c..9028c4801 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit 97066e40ccd061f727deb5cd860e4d9135aa2551 +Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8 diff --git a/ethstore/src/dir/disk.rs b/ethstore/src/dir/disk.rs index 6616ec15d..56b2c1ccb 100644 --- a/ethstore/src/dir/disk.rs +++ b/ethstore/src/dir/disk.rs @@ -20,6 +20,7 @@ use std::collections::HashMap; use time; use ethkey::Address; use {json, SafeAccount, Error}; +use json::UUID; use super::KeyDirectory; const IGNORED_FILES: &'static [&'static str] = &["thumbs.db", "address_book.json"]; @@ -112,7 +113,7 @@ impl KeyDirectory for DiskDirectory { // build file path let filename = account.filename.as_ref().cloned().unwrap_or_else(|| { let timestamp = time::strftime("%Y-%m-%dT%H-%M-%S", &time::now_utc()).expect("Time-format string is valid."); - format!("UTC--{}Z--{:?}", timestamp, account.address) + format!("UTC--{}Z--{}", timestamp, UUID::from(account.id)) }); // update account filename diff --git a/js/package.json b/js/package.json index 59b75c591..2a2b6d590 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.49", + "version": "0.2.50", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", @@ -122,6 +122,7 @@ "brace": "^0.9.0", "bytes": "^2.4.0", "chart.js": "^2.3.0", + "es6-error": "^4.0.0", "es6-promise": "^3.2.1", "ethereumjs-tx": "^1.1.2", "file-saver": "^1.3.3", diff --git a/js/scripts/release.sh b/js/scripts/release.sh index 5e631cf98..3ff4a577c 100755 --- a/js/scripts/release.sh +++ b/js/scripts/release.sh @@ -68,11 +68,13 @@ if [ "$BRANCH" == "master" ]; then fi echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH" +git submodule update cargo update -p parity-ui-precompiled # --precise "$PRECOMPILED_HASH" echo "*** Committing updated files" -git add . +git add js +git add Cargo.lock git commit -m "[ci skip] js-precompiled $UTCDATE" git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG diff --git a/js/src/api/transport/error.js b/js/src/api/transport/error.js new file mode 100644 index 000000000..341839f69 --- /dev/null +++ b/js/src/api/transport/error.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 ExtendableError from 'es6-error'; + +export const ERROR_CODES = { + UNSUPPORTED_REQUEST: -32000, + NO_WORK: -32001, + NO_AUTHOR: -32002, + NO_NEW_WORK: -32003, + NOT_ENOUGH_DATA: -32006, + UNKNOWN_ERROR: -32009, + TRANSACTION_ERROR: -32010, + EXECUTION_ERROR: -32015, + ACCOUNT_LOCKED: -32020, + PASSWORD_INVALID: -32021, + ACCOUNT_ERROR: -32023, + SIGNER_DISABLED: -32030, + DAPPS_DISABLED: -32031, + NETWORK_DISABLED: -32035, + REQUEST_REJECTED: -32040, + REQUEST_REJECTED_LIMIT: -32041, + REQUEST_NOT_FOUND: -32042, + COMPILATION_ERROR: -32050, + ENCRYPTION_ERROR: -32055, + FETCH_ERROR: -32060 +}; + +export default class TransportError extends ExtendableError { + constructor (method, code, message) { + const m = `${method}: ${code}: ${message}`; + super(m); + + this.code = code; + this.type = Object.keys(ERROR_CODES).find((k) => ERROR_CODES[k] === code) || ''; + + this.method = method; + this.text = message; + } +} diff --git a/js/src/api/transport/http/http.js b/js/src/api/transport/http/http.js index 8ea59f0fb..591b9a627 100644 --- a/js/src/api/transport/http/http.js +++ b/js/src/api/transport/http/http.js @@ -16,6 +16,7 @@ import { Logging } from '../../subscriptions'; import JsonRpcBase from '../jsonRpcBase'; +import TransportError from '../error'; /* global fetch */ export default class Http extends JsonRpcBase { @@ -73,7 +74,8 @@ export default class Http extends JsonRpcBase { this.error(JSON.stringify(response)); console.error(`${method}(${JSON.stringify(params)}): ${response.error.code}: ${response.error.message}`); - throw new Error(`${method}: ${response.error.code}: ${response.error.message}`); + const error = new TransportError(method, response.error.code, response.error.message); + throw error; } this.log(JSON.stringify(response)); diff --git a/js/src/api/transport/index.js b/js/src/api/transport/index.js index 8f67fba4d..84fbac826 100644 --- a/js/src/api/transport/index.js +++ b/js/src/api/transport/index.js @@ -16,3 +16,4 @@ export Http from './http'; export Ws from './ws'; +export TransportError from './error.js'; diff --git a/js/src/api/transport/ws/ws.js b/js/src/api/transport/ws/ws.js index d608426b0..1cb1fb1c4 100644 --- a/js/src/api/transport/ws/ws.js +++ b/js/src/api/transport/ws/ws.js @@ -18,6 +18,7 @@ import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase import { Logging } from '../../subscriptions'; import JsonRpcBase from '../jsonRpcBase'; +import TransportError from '../error'; /* global WebSocket */ export default class Ws extends JsonRpcBase { @@ -109,7 +110,9 @@ export default class Ws extends JsonRpcBase { console.error(`${method}(${JSON.stringify(params)}): ${result.error.code}: ${result.error.message}`); - reject(new Error(`${method}: ${result.error.code}: ${result.error.message}`)); + const error = new TransportError(method, result.error.code, result.error.message); + reject(error); + delete this._messages[result.id]; return; } diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index a99b49412..996948092 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -26,6 +26,8 @@ import ErrorStep from './ErrorStep'; import styles from './deployContract.css'; +import { ERROR_CODES } from '../../api/transport/error'; + const steps = ['contract details', 'deployment', 'completed']; export default class DeployContract extends Component { @@ -63,7 +65,8 @@ export default class DeployContract extends Component { params: [], paramsError: [], step: 0, - deployError: null + deployError: null, + rejected: false } componentWillMount () { @@ -92,15 +95,20 @@ export default class DeployContract extends Component { } render () { - const { step, deployError } = this.state; + const { step, deployError, rejected } = this.state; + + const realSteps = deployError || rejected ? null : steps; + const title = realSteps + ? null + : (deployError ? 'deployment failed' : 'rejected'); return ( { this.renderStep() } @@ -158,7 +166,7 @@ export default class DeployContract extends Component { renderStep () { const { accounts, readOnly } = this.props; - const { address, deployError, step, deployState, txhash } = this.state; + const { address, deployError, step, deployState, txhash, rejected } = this.state; if (deployError) { return ( @@ -166,6 +174,15 @@ export default class DeployContract extends Component { ); } + if (rejected) { + return ( + + ); + } + switch (step) { case 0: return ( @@ -273,6 +290,11 @@ export default class DeployContract extends Component { }); }) .catch((error) => { + if (error.code === ERROR_CODES.REQUEST_REJECTED) { + this.setState({ rejected: true }); + return false; + } + console.error('error deploying contract', error); this.setState({ deployError: error }); store.dispatch({ type: 'newError', error }); diff --git a/js/src/modals/ExecuteContract/executeContract.js b/js/src/modals/ExecuteContract/executeContract.js index b45cf6875..a57c18a1d 100644 --- a/js/src/modals/ExecuteContract/executeContract.js +++ b/js/src/modals/ExecuteContract/executeContract.js @@ -23,6 +23,8 @@ import { validateAddress, validateUint } from '../../util/validation'; import DetailsStep from './DetailsStep'; +import { ERROR_CODES } from '../../api/transport/error'; + export default class ExecuteContract extends Component { static contextTypes = { api: PropTypes.object.isRequired, @@ -49,7 +51,8 @@ export default class ExecuteContract extends Component { step: 0, sending: false, busyState: null, - txhash: null + txhash: null, + rejected: false } componentDidMount () { @@ -80,6 +83,7 @@ export default class ExecuteContract extends Component { const { onClose, fromAddress } = this.props; const { sending, step, fromAddressError, valuesError } = this.state; const hasError = fromAddressError || valuesError.find((error) => error); + const cancelBtn = (