merge master into jr-first-run
This commit is contained in:
commit
bbcae3d27b
35
Cargo.lock
generated
35
Cargo.lock
generated
@ -530,6 +530,7 @@ dependencies = [
|
|||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"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-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-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)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "jsonrpc-core"
|
name = "jsonrpc-core"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53"
|
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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 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_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)",
|
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -872,7 +873,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-http-server"
|
name = "jsonrpc-http-server"
|
||||||
version = "6.1.1"
|
version = "6.1.1"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53"
|
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
@ -883,7 +884,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-ipc-server"
|
name = "jsonrpc-ipc-server"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53"
|
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "jsonrpc-tcp-server"
|
name = "jsonrpc-tcp-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53"
|
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1290,22 +1300,11 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-ui-precompiled"
|
name = "parity-ui-precompiled"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "git+https://github.com/ethcore/js-precompiled.git#eb9d978ed5ad1c514b37e89c716f80b3c8d613b5"
|
source = "git+https://github.com/ethcore/js-precompiled.git#175003ae159b126302fd1a90dd875dc86d7adba0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
@ -2065,6 +2064,7 @@ dependencies = [
|
|||||||
"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
|
"checksum jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"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"
|
"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 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-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)" = "<none>"
|
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "<none>"
|
||||||
"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 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 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"
|
"checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026"
|
||||||
|
@ -10,14 +10,15 @@
|
|||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"homesteadTransition": "0x118c30",
|
"homesteadTransition": 1150000,
|
||||||
"eip150Transition": "0x2625a0",
|
"eip150Transition": 2500000,
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
"eip155Transition": 3000000,
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": 3000000,
|
||||||
|
"ecip1010PauseTransition": 3000000,
|
||||||
|
"ecip1010ContinueTransition": 5000000,
|
||||||
|
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff",
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
"ecip1010PauseTransition": "0x2dc6c0",
|
|
||||||
"ecip1010ContinueTransition": "0x4c4b40"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -9,12 +9,15 @@
|
|||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
||||||
"homesteadTransition": "0x789b0",
|
"homesteadTransition": 494000,
|
||||||
"eip150Transition": "0x1b34d8",
|
"eip150Transition": 1783000,
|
||||||
"eip155Transition": 1885000,
|
"eip155Transition": 1915000,
|
||||||
"eip160Transition": 1885000,
|
"eip160Transition": 1915000,
|
||||||
"eip161abcTransition": 1885000,
|
"ecip1010PauseTransition": 1915000,
|
||||||
"eip161dTransition": 1885000
|
"ecip1010ContinueTransition": 3415000,
|
||||||
|
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be
|
Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.2.119",
|
"version": "0.2.122",
|
||||||
"main": "release/index.js",
|
"main": "release/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
"jsnext:main": "src/index.js",
|
||||||
"author": "Parity Team <admin@parity.io>",
|
"author": "Parity Team <admin@parity.io>",
|
||||||
|
33
js/src/3rdparty/email-verification/index.js
vendored
Normal file
33
js/src/3rdparty/email-verification/index.js
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { stringify } from 'querystring';
|
||||||
|
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
23
js/src/3rdparty/email-verification/terms-of-service.js
vendored
Normal file
23
js/src/3rdparty/email-verification/terms-of-service.js
vendored
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default (
|
||||||
|
<ul>
|
||||||
|
<li>todo</li>
|
||||||
|
</ul>
|
||||||
|
);
|
11
js/src/3rdparty/sms-verification/index.js
vendored
11
js/src/3rdparty/sms-verification/index.js
vendored
@ -15,17 +15,6 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { stringify } from 'querystring';
|
import { stringify } from 'querystring';
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
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>
|
|
||||||
<li>You pay a fee for the cost of this service using the account you want to verify.</li>
|
|
||||||
<li>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: <a href={ 'https://www.twilio.com/legal/privacy/developer' }>https://www.twilio.com/legal/privacy/developer</a>.</li>
|
|
||||||
<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, isTestnet = false) => {
|
export const postToServer = (query, isTestnet = false) => {
|
||||||
const port = isTestnet ? 8443 : 443;
|
const port = isTestnet ? 8443 : 443;
|
||||||
|
27
js/src/3rdparty/sms-verification/terms-of-service.js
vendored
Normal file
27
js/src/3rdparty/sms-verification/terms-of-service.js
vendored
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default (
|
||||||
|
<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>
|
||||||
|
<li>You pay a fee for the cost of this service using the account you want to verify.</li>
|
||||||
|
<li>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: <a href={ 'https://www.twilio.com/legal/privacy/developer' }>https://www.twilio.com/legal/privacy/developer</a>.</li>
|
||||||
|
<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>
|
||||||
|
);
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import blockies from 'blockies';
|
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) {
|
export function createIdentityImg (address, scale = 8) {
|
||||||
return blockies({
|
return TEST_ENV
|
||||||
seed: (address || '').toLowerCase(),
|
? ''
|
||||||
size: 8,
|
: blockies({
|
||||||
scale
|
seed: (address || '').toLowerCase(),
|
||||||
}).toDataURL();
|
size: 8,
|
||||||
|
scale
|
||||||
|
}).toDataURL();
|
||||||
}
|
}
|
||||||
|
1
js/src/contracts/abi/email-verification.json
Normal file
1
js/src/contracts/abi/email-verification.json
Normal file
@ -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":[{"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"}]
|
@ -19,6 +19,7 @@ import basiccoin from './basiccoin.json';
|
|||||||
import basiccoinmanager from './basiccoinmanager.json';
|
import basiccoinmanager from './basiccoinmanager.json';
|
||||||
import dappreg from './dappreg.json';
|
import dappreg from './dappreg.json';
|
||||||
import eip20 from './eip20.json';
|
import eip20 from './eip20.json';
|
||||||
|
import emailverification from './email-verification.json';
|
||||||
import gavcoin from './gavcoin.json';
|
import gavcoin from './gavcoin.json';
|
||||||
import githubhint from './githubhint.json';
|
import githubhint from './githubhint.json';
|
||||||
import owned from './owned.json';
|
import owned from './owned.json';
|
||||||
@ -34,6 +35,7 @@ export {
|
|||||||
basiccoinmanager,
|
basiccoinmanager,
|
||||||
dappreg,
|
dappreg,
|
||||||
eip20,
|
eip20,
|
||||||
|
emailverification,
|
||||||
gavcoin,
|
gavcoin,
|
||||||
githubhint,
|
githubhint,
|
||||||
owned,
|
owned,
|
||||||
|
@ -19,7 +19,7 @@ import Registry from './registry';
|
|||||||
import SignatureReg from './signaturereg';
|
import SignatureReg from './signaturereg';
|
||||||
import TokenReg from './tokenreg';
|
import TokenReg from './tokenreg';
|
||||||
import GithubHint from './githubhint';
|
import GithubHint from './githubhint';
|
||||||
import * as smsVerification from './sms-verification';
|
import * as verification from './verification';
|
||||||
import BadgeReg from './badgereg';
|
import BadgeReg from './badgereg';
|
||||||
|
|
||||||
let instance = null;
|
let instance = null;
|
||||||
@ -58,7 +58,11 @@ export default class Contracts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get smsVerification () {
|
get smsVerification () {
|
||||||
return smsVerification;
|
return verification;
|
||||||
|
}
|
||||||
|
|
||||||
|
get emailVerification () {
|
||||||
|
return verification;
|
||||||
}
|
}
|
||||||
|
|
||||||
static create (api) {
|
static create (api) {
|
||||||
|
@ -58,23 +58,23 @@ export default class DetailsStep extends Component {
|
|||||||
<Form>
|
<Form>
|
||||||
{ this.renderWarning() }
|
{ this.renderWarning() }
|
||||||
<AddressSelect
|
<AddressSelect
|
||||||
label='from account'
|
|
||||||
hint='the account to transact with'
|
|
||||||
value={ fromAddress }
|
|
||||||
error={ fromAddressError }
|
|
||||||
accounts={ accounts }
|
accounts={ accounts }
|
||||||
balances={ balances }
|
balances={ balances }
|
||||||
onChange={ onFromAddressChange } />
|
error={ fromAddressError }
|
||||||
|
hint='the account to transact with'
|
||||||
|
label='from account'
|
||||||
|
onChange={ onFromAddressChange }
|
||||||
|
value={ fromAddress } />
|
||||||
{ this.renderFunctionSelect() }
|
{ this.renderFunctionSelect() }
|
||||||
{ this.renderParameters() }
|
{ this.renderParameters() }
|
||||||
<div className={ styles.columns }>
|
<div className={ styles.columns }>
|
||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
label='transaction value (in ETH)'
|
|
||||||
hint='the amount to send to with the transaction'
|
|
||||||
value={ amount }
|
|
||||||
error={ amountError }
|
error={ amountError }
|
||||||
onSubmit={ onAmountChange } />
|
hint='the amount to send to with the transaction'
|
||||||
|
label='transaction value (in ETH)'
|
||||||
|
onSubmit={ onAmountChange }
|
||||||
|
value={ amount } />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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(
|
||||||
|
<ContextProvider api={ {} } muiTheme={ muiTheme } store={ {} }>
|
||||||
|
<DetailsStep
|
||||||
|
{ ...props }
|
||||||
|
contract={ CONTRACT }
|
||||||
|
onAmountChange={ onAmountChange }
|
||||||
|
onClose={ onClose }
|
||||||
|
onFromAddressChange={ onFromAddressChange }
|
||||||
|
onFuncChange={ onFuncChange }
|
||||||
|
onGasEditClick={ onGasEditClick }
|
||||||
|
onValueChange={ onValueChange } />
|
||||||
|
</ContextProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -25,6 +25,7 @@ import ContentClear from 'material-ui/svg-icons/content/clear';
|
|||||||
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
|
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
|
||||||
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
|
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 { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash } from '~/ui';
|
||||||
import { MAX_GAS_ESTIMATION } from '~/util/constants';
|
import { MAX_GAS_ESTIMATION } from '~/util/constants';
|
||||||
import { validateAddress, validateUint } from '~/util/validation';
|
import { validateAddress, validateUint } from '~/util/validation';
|
||||||
@ -56,12 +57,12 @@ class ExecuteContract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
isTest: PropTypes.bool,
|
|
||||||
fromAddress: PropTypes.string,
|
|
||||||
accounts: PropTypes.object,
|
accounts: PropTypes.object,
|
||||||
balances: PropTypes.object,
|
balances: PropTypes.object,
|
||||||
contract: PropTypes.object,
|
contract: PropTypes.object.isRequired,
|
||||||
|
fromAddress: PropTypes.string,
|
||||||
gasLimit: PropTypes.object.isRequired,
|
gasLimit: PropTypes.object.isRequired,
|
||||||
|
isTest: PropTypes.bool,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
onFromAddressChange: PropTypes.func.isRequired
|
onFromAddressChange: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
@ -77,11 +78,11 @@ class ExecuteContract extends Component {
|
|||||||
funcError: null,
|
funcError: null,
|
||||||
gasEdit: false,
|
gasEdit: false,
|
||||||
rejected: false,
|
rejected: false,
|
||||||
step: STEP_DETAILS,
|
|
||||||
sending: false,
|
sending: false,
|
||||||
|
step: STEP_DETAILS,
|
||||||
|
txhash: null,
|
||||||
values: [],
|
values: [],
|
||||||
valuesError: [],
|
valuesError: []
|
||||||
txhash: null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
@ -255,10 +256,6 @@ class ExecuteContract extends Component {
|
|||||||
valueError = validateAddress(_value).addressError;
|
valueError = validateAddress(_value).addressError;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bool':
|
|
||||||
value = _value === 'true';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'uint':
|
case 'uint':
|
||||||
valueError = validateUint(_value).valueError;
|
valueError = validateUint(_value).valueError;
|
||||||
break;
|
break;
|
||||||
@ -278,13 +275,12 @@ class ExecuteContract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
estimateGas = (_fromAddress) => {
|
estimateGas = (_fromAddress) => {
|
||||||
const { api } = this.context;
|
|
||||||
const { fromAddress } = this.props;
|
const { fromAddress } = this.props;
|
||||||
const { amount, func, values } = this.state;
|
const { amount, func, values } = this.state;
|
||||||
const options = {
|
const options = {
|
||||||
gas: MAX_GAS_ESTIMATION,
|
gas: MAX_GAS_ESTIMATION,
|
||||||
from: _fromAddress || fromAddress,
|
from: _fromAddress || fromAddress,
|
||||||
value: api.util.toWei(amount || 0)
|
value: toWei(amount || 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
|
69
js/src/modals/ExecuteContract/executeContract.spec.js
Normal file
69
js/src/modals/ExecuteContract/executeContract.spec.js
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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(
|
||||||
|
<ExecuteContract
|
||||||
|
{ ...props }
|
||||||
|
contract={ CONTRACT }
|
||||||
|
onClose={ onClose }
|
||||||
|
onFromAddressChange={ onFromAddressChange } />,
|
||||||
|
{ 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]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
64
js/src/modals/ExecuteContract/executeContract.test.js
Normal file
64
js/src/modals/ExecuteContract/executeContract.test.js
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
@ -15,10 +15,6 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.list li {
|
|
||||||
padding: .1em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spacing {
|
.spacing {
|
||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
}
|
}
|
@ -25,41 +25,33 @@ import { fromWei } from '~/api/util/wei';
|
|||||||
import { Form, Input } from '~/ui';
|
import { Form, Input } from '~/ui';
|
||||||
import { nullableProptype } from '~/util/proptypes';
|
import { nullableProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import { termsOfService } from '../../../3rdparty/sms-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';
|
import styles from './gatherData.css';
|
||||||
|
|
||||||
export default class GatherData extends Component {
|
export default class GatherData extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
fee: React.PropTypes.instanceOf(BigNumber),
|
fee: React.PropTypes.instanceOf(BigNumber),
|
||||||
isNumberValid: PropTypes.bool.isRequired,
|
method: PropTypes.string.isRequired,
|
||||||
|
fields: PropTypes.array.isRequired,
|
||||||
isVerified: nullableProptype(PropTypes.bool.isRequired),
|
isVerified: nullableProptype(PropTypes.bool.isRequired),
|
||||||
hasRequested: nullableProptype(PropTypes.bool.isRequired),
|
hasRequested: nullableProptype(PropTypes.bool.isRequired),
|
||||||
setNumber: PropTypes.func.isRequired,
|
|
||||||
setConsentGiven: PropTypes.func.isRequired
|
setConsentGiven: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isNumberValid, isVerified } = this.props;
|
const { method, isVerified } = this.props;
|
||||||
|
const termsOfService = method === 'email' ? emailTermsOfService : smsTermsOfService;
|
||||||
|
const howItWorks = method === 'email' ? howEmailVerificationWorks : howSMSVerificationWorks;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<p>The following steps will let you prove that you control both an account and a phone number.</p>
|
{ howItWorks }
|
||||||
<ol className={ styles.list }>
|
|
||||||
<li>You send a verification request to a specific contract.</li>
|
|
||||||
<li>Our server puts a puzzle into this contract.</li>
|
|
||||||
<li>The code you receive via SMS is the solution to this puzzle.</li>
|
|
||||||
</ol>
|
|
||||||
{ this.renderFee() }
|
{ this.renderFee() }
|
||||||
{ this.renderCertified() }
|
{ this.renderCertified() }
|
||||||
{ this.renderRequested() }
|
{ this.renderRequested() }
|
||||||
<Input
|
{ this.renderFields() }
|
||||||
label={ 'phone number in international format' }
|
|
||||||
hint={ 'the SMS will be sent to this number' }
|
|
||||||
error={ isNumberValid ? null : 'invalid number' }
|
|
||||||
disabled={ isVerified }
|
|
||||||
onChange={ this.numberOnChange }
|
|
||||||
onSubmit={ this.numberOnSubmit }
|
|
||||||
/>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
className={ styles.spacing }
|
className={ styles.spacing }
|
||||||
label={ 'I agree to the terms and conditions below.' }
|
label={ 'I agree to the terms and conditions below.' }
|
||||||
@ -136,12 +128,28 @@ export default class GatherData extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
numberOnSubmit = (value) => {
|
renderFields () {
|
||||||
this.props.setNumber(value);
|
const { isVerified, fields } = this.props;
|
||||||
}
|
|
||||||
|
|
||||||
numberOnChange = (_, value) => {
|
const rendered = fields.map((field) => {
|
||||||
this.props.setNumber(value);
|
const onChange = (_, v) => {
|
||||||
|
field.onChange(v);
|
||||||
|
};
|
||||||
|
const onSubmit = field.onChange;
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
key={ field.key }
|
||||||
|
label={ field.label }
|
||||||
|
hint={ field.hint }
|
||||||
|
error={ field.error }
|
||||||
|
disabled={ isVerified }
|
||||||
|
onChange={ onChange }
|
||||||
|
onSubmit={ onSubmit }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (<div>{rendered}</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
consentOnChange = (_, consentGiven) => {
|
consentOnChange = (_, consentGiven) => {
|
@ -20,20 +20,25 @@ import { Form, Input } from '~/ui';
|
|||||||
|
|
||||||
export default class QueryCode extends Component {
|
export default class QueryCode extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
number: PropTypes.string.isRequired,
|
receiver: PropTypes.string.isRequired,
|
||||||
|
hint: PropTypes.string,
|
||||||
isCodeValid: PropTypes.bool.isRequired,
|
isCodeValid: PropTypes.bool.isRequired,
|
||||||
setCode: PropTypes.func.isRequired
|
setCode: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
hint: 'Enter the code you received.'
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { number, isCodeValid } = this.props;
|
const { receiver, hint, isCodeValid } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<p>The verification code has been sent to { number }.</p>
|
<p>The verification code has been sent to { receiver }.</p>
|
||||||
<Input
|
<Input
|
||||||
label={ 'verification code' }
|
label={ 'verification code' }
|
||||||
hint={ 'Enter the code you received via SMS.' }
|
hint={ hint }
|
||||||
error={ isCodeValid ? null : 'invalid code' }
|
error={ isCodeValid ? null : 'invalid code' }
|
||||||
onChange={ this.onChange }
|
onChange={ this.onChange }
|
||||||
onSubmit={ this.onSubmit }
|
onSubmit={ this.onSubmit }
|
@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { nullableProptype } from '~/util/proptypes';
|
import { nullableProptype } from '~/util/proptypes';
|
||||||
import TxHash from '~/ui/TxHash';
|
import TxHash from '~/ui/TxHash';
|
||||||
import {
|
import {
|
||||||
POSTING_REQUEST, POSTED_REQUEST, REQUESTING_SMS
|
POSTING_REQUEST, POSTED_REQUEST, REQUESTING_CODE
|
||||||
} from '../store';
|
} from '../store';
|
||||||
|
|
||||||
import styles from './sendRequest.css';
|
import styles from './sendRequest.css';
|
||||||
@ -45,9 +45,9 @@ export default class SendRequest extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
case REQUESTING_SMS:
|
case REQUESTING_CODE:
|
||||||
return (
|
return (
|
||||||
<p>Requesting an SMS from the Parity server and waiting for the puzzle to be put into the contract.</p>
|
<p>Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
70
js/src/modals/Verification/email-store.js
Normal file
70
js/src/modals/Verification/email-store.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { observable, computed, action } from 'mobx';
|
||||||
|
import { 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';
|
||||||
|
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) {
|
||||||
|
super(api, EmailVerificationABI, 'emailverification3', account, isTestnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestValues = () => [ sha3(this.email) ]
|
||||||
|
|
||||||
|
@action setEmail = (email) => {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCode = () => {
|
||||||
|
const { email, account, isTestnet } = this;
|
||||||
|
return postToServer({ email, address: account }, isTestnet);
|
||||||
|
}
|
||||||
|
}
|
41
js/src/modals/Verification/how-it-works.js
Normal file
41
js/src/modals/Verification/how-it-works.js
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import styles from './verification.css';
|
||||||
|
|
||||||
|
export const howSMSVerificationWorks = (
|
||||||
|
<div>
|
||||||
|
<p>The following steps will let you prove that you control both an account and a phone number.</p>
|
||||||
|
<ol className={ styles.list }>
|
||||||
|
<li>You send a verification request to a specific contract.</li>
|
||||||
|
<li>Our server puts a puzzle into this contract.</li>
|
||||||
|
<li>The code you receive via SMS is the solution to this puzzle.</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const howEmailVerificationWorks = (
|
||||||
|
<div>
|
||||||
|
<p>The following steps will let you prove that you control both an account and an e-mail address.</p>
|
||||||
|
<ol className={ styles.list }>
|
||||||
|
<li>You send a verification request to a specific contract.</li>
|
||||||
|
<li>Our server puts a puzzle into this contract.</li>
|
||||||
|
<li>The code you receive via e-mail is the solution to this puzzle.</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
);
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
// This file is part of Parity.
|
// This file is part of Parity.
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
@ -14,4 +14,4 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
export default from './SMSVerification';
|
export default from './verification';
|
67
js/src/modals/Verification/sms-store.js
Normal file
67
js/src/modals/Verification/sms-store.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { observable, computed, action } from 'mobx';
|
||||||
|
import phone from 'phoneformat.js';
|
||||||
|
|
||||||
|
import 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';
|
||||||
|
|
||||||
|
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) {
|
||||||
|
super(api, SMSVerificationABI, 'smsverification', account, isTestnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action setNumber = (number) => {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCode = () => {
|
||||||
|
const { number, account, isTestnet } = this;
|
||||||
|
return postToServer({ number, address: account }, isTestnet);
|
||||||
|
}
|
||||||
|
}
|
@ -14,21 +14,19 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { observable, computed, autorun, action } from 'mobx';
|
import { observable, autorun, action } from 'mobx';
|
||||||
import phone from 'phoneformat.js';
|
|
||||||
import { sha3 } from '~/api/util/sha3';
|
import { sha3 } from '~/api/util/sha3';
|
||||||
|
import Contract from '~/api/contract';
|
||||||
import Contracts from '~/contracts';
|
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, waitForConfirmations } from '~/util/tx';
|
import { checkIfTxFailed, waitForConfirmations } from '~/util/tx';
|
||||||
|
|
||||||
export const LOADING = 'fetching-contract';
|
export const LOADING = 'fetching-contract';
|
||||||
export const QUERY_DATA = 'query-data';
|
export const QUERY_DATA = 'query-data';
|
||||||
export const POSTING_REQUEST = 'posting-request';
|
export const POSTING_REQUEST = 'posting-request';
|
||||||
export const POSTED_REQUEST = 'posted-request';
|
export const POSTED_REQUEST = 'posted-request';
|
||||||
export const REQUESTING_SMS = 'requesting-sms';
|
export const REQUESTING_CODE = 'requesting-code';
|
||||||
export const QUERY_CODE = 'query-code';
|
export const QUERY_CODE = 'query-code';
|
||||||
export const POSTING_CONFIRMATION = 'posting-confirmation';
|
export const POSTING_CONFIRMATION = 'posting-confirmation';
|
||||||
export const POSTED_CONFIRMATION = 'posted-confirmation';
|
export const POSTED_CONFIRMATION = 'posted-confirmation';
|
||||||
@ -43,56 +41,30 @@ export default class VerificationStore {
|
|||||||
@observable isVerified = null;
|
@observable isVerified = null;
|
||||||
@observable hasRequested = null;
|
@observable hasRequested = null;
|
||||||
@observable consentGiven = false;
|
@observable consentGiven = false;
|
||||||
@observable number = '';
|
|
||||||
@observable requestTx = null;
|
@observable requestTx = null;
|
||||||
@observable code = '';
|
@observable code = '';
|
||||||
@observable isCodeValid = null;
|
@observable isCodeValid = null;
|
||||||
@observable confirmationTx = null;
|
@observable confirmationTx = null;
|
||||||
|
|
||||||
@computed get isNumberValid () {
|
constructor (api, abi, name, account, isTestnet) {
|
||||||
return phone.isValidNumber(this.number);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get isStepValid () {
|
|
||||||
if (this.step === DONE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (this.error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.step) {
|
|
||||||
case LOADING:
|
|
||||||
return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
|
|
||||||
case QUERY_DATA:
|
|
||||||
return this.isNumberValid && this.consentGiven;
|
|
||||||
case QUERY_CODE:
|
|
||||||
return this.requestTx && this.isCodeValid === true;
|
|
||||||
case POSTED_CONFIRMATION:
|
|
||||||
return !!this.confirmationTx;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor (api, account, isTestnet) {
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.isTestnet = isTestnet;
|
this.isTestnet = isTestnet;
|
||||||
|
|
||||||
this.step = LOADING;
|
this.step = LOADING;
|
||||||
Contracts.create(api).registry.getContract('smsverification')
|
Contracts.get().badgeReg.fetchCertifier(name)
|
||||||
.then((contract) => {
|
.then(({ address }) => {
|
||||||
this.contract = contract;
|
this.contract = new Contract(api, abi).at(address);
|
||||||
this.load();
|
this.load();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
console.error('error', err);
|
||||||
this.error = 'Failed to fetch the contract: ' + err.message;
|
this.error = 'Failed to fetch the contract: ' + err.message;
|
||||||
});
|
});
|
||||||
|
|
||||||
autorun(() => {
|
autorun(() => {
|
||||||
if (this.error) {
|
if (this.error) {
|
||||||
console.error('sms verification: ' + this.error);
|
console.error('verification: ' + this.error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -135,10 +107,6 @@ export default class VerificationStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action setNumber = (number) => {
|
|
||||||
this.number = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@action setConsentGiven = (consentGiven) => {
|
@action setConsentGiven = (consentGiven) => {
|
||||||
this.consentGiven = consentGiven;
|
this.consentGiven = consentGiven;
|
||||||
}
|
}
|
||||||
@ -166,19 +134,22 @@ export default class VerificationStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestValues = () => []
|
||||||
|
|
||||||
@action sendRequest = () => {
|
@action sendRequest = () => {
|
||||||
const { api, account, contract, fee, number, hasRequested } = this;
|
const { api, account, contract, fee, hasRequested } = this;
|
||||||
|
|
||||||
const request = contract.functions.find((fn) => fn.name === 'request');
|
const request = contract.functions.find((fn) => fn.name === 'request');
|
||||||
const options = { from: account, value: fee.toString() };
|
const options = { from: account, value: fee.toString() };
|
||||||
|
const values = this.requestValues();
|
||||||
|
|
||||||
let chain = Promise.resolve();
|
let chain = Promise.resolve();
|
||||||
if (!hasRequested) {
|
if (!hasRequested) {
|
||||||
this.step = POSTING_REQUEST;
|
this.step = POSTING_REQUEST;
|
||||||
chain = request.estimateGas(options, [])
|
chain = request.estimateGas(options, values)
|
||||||
.then((gas) => {
|
.then((gas) => {
|
||||||
options.gas = gas.mul(1.2).toFixed(0);
|
options.gas = gas.mul(1.2).toFixed(0);
|
||||||
return request.postTransaction(options, []);
|
return request.postTransaction(options, values);
|
||||||
})
|
})
|
||||||
.then((handle) => {
|
.then((handle) => {
|
||||||
// TODO: The "request rejected" error doesn't have any property to
|
// TODO: The "request rejected" error doesn't have any property to
|
||||||
@ -200,18 +171,15 @@ export default class VerificationStore {
|
|||||||
|
|
||||||
chain
|
chain
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return api.parity.netChain();
|
this.step = REQUESTING_CODE;
|
||||||
})
|
return this.requestCode();
|
||||||
.then((chain) => {
|
|
||||||
this.step = REQUESTING_SMS;
|
|
||||||
return postToServer({ number, address: account }, this.isTestnet);
|
|
||||||
})
|
})
|
||||||
.then(() => awaitPuzzle(api, contract, account))
|
.then(() => awaitPuzzle(api, contract, account))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.step = QUERY_CODE;
|
this.step = QUERY_CODE;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.error = 'Failed to request a confirmation SMS: ' + err.message;
|
this.error = 'Failed to request a confirmation code: ' + err.message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
25
js/src/modals/Verification/verification.css
Normal file
25
js/src/modals/Verification/verification.css
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.noSpacing {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list li {
|
||||||
|
padding: .1em 0;
|
||||||
|
}
|
@ -20,12 +20,27 @@ import DoneIcon from 'material-ui/svg-icons/action/done-all';
|
|||||||
import CancelIcon from 'material-ui/svg-icons/content/clear';
|
import CancelIcon from 'material-ui/svg-icons/content/clear';
|
||||||
|
|
||||||
import { Button, IdentityIcon, Modal } from '~/ui';
|
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',
|
||||||
|
description: (<p className={ styles.noSpacing }>It will be stored on the blockchain that you control a phone number (not <em>which</em>).</p>)
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
label: 'E-mail Verification', key: 1, value: 'email',
|
||||||
|
description: (<p className={ styles.noSpacing }>The hash of the e-mail address you prove control over will be stored on the blockchain.</p>)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LOADING,
|
LOADING,
|
||||||
QUERY_DATA,
|
QUERY_DATA,
|
||||||
POSTING_REQUEST, POSTED_REQUEST,
|
POSTING_REQUEST, POSTED_REQUEST,
|
||||||
REQUESTING_SMS, QUERY_CODE,
|
REQUESTING_CODE, QUERY_CODE,
|
||||||
POSTING_CONFIRMATION, POSTED_CONFIRMATION,
|
POSTING_CONFIRMATION, POSTED_CONFIRMATION,
|
||||||
DONE
|
DONE
|
||||||
} from './store';
|
} from './store';
|
||||||
@ -37,34 +52,44 @@ import SendConfirmation from './SendConfirmation';
|
|||||||
import Done from './Done';
|
import Done from './Done';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class SMSVerification extends Component {
|
export default class Verification extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
store: PropTypes.any.isRequired,
|
store: nullableProptype(PropTypes.object.isRequired),
|
||||||
account: PropTypes.string.isRequired,
|
account: PropTypes.string.isRequired,
|
||||||
|
onSelectMethod: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired
|
onClose: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
static phases = { // mapping (store steps -> steps)
|
static phases = { // mapping (store steps -> steps)
|
||||||
[LOADING]: 0,
|
[LOADING]: 1, [QUERY_DATA]: 1,
|
||||||
[QUERY_DATA]: 1,
|
[POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2,
|
||||||
[POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_SMS]: 2,
|
|
||||||
[QUERY_CODE]: 3,
|
[QUERY_CODE]: 3,
|
||||||
[POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4,
|
[POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4,
|
||||||
[DONE]: 5
|
[DONE]: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
method: 'sms'
|
||||||
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const phase = SMSVerification.phases[this.props.store.step];
|
const { store } = this.props;
|
||||||
const { error, isStepValid } = this.props.store;
|
let phase = 0; let error = false; let isStepValid = true;
|
||||||
|
|
||||||
|
if (store) {
|
||||||
|
phase = Verification.phases[store.step];
|
||||||
|
error = store.error;
|
||||||
|
isStepValid = store.isStepValid;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
actions={ this.renderDialogActions(phase, error, isStepValid) }
|
actions={ this.renderDialogActions(phase, error, isStepValid) }
|
||||||
title='verify your account via SMS'
|
title='verify your account'
|
||||||
visible
|
visible
|
||||||
current={ phase }
|
current={ phase }
|
||||||
steps={ ['Prepare', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] }
|
steps={ ['Method', 'Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] }
|
||||||
waiting={ error ? [] : [ 0, 2, 4 ] }
|
waiting={ error ? [] : [ 2, 4 ] }
|
||||||
>
|
>
|
||||||
{ this.renderStep(phase, error) }
|
{ this.renderStep(phase, error) }
|
||||||
</Modal>
|
</Modal>
|
||||||
@ -101,6 +126,13 @@ export default class SMSVerification extends Component {
|
|||||||
|
|
||||||
let action = () => {};
|
let action = () => {};
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
|
case 0:
|
||||||
|
action = () => {
|
||||||
|
const { onSelectMethod } = this.props;
|
||||||
|
const { method } = this.state;
|
||||||
|
onSelectMethod(method);
|
||||||
|
};
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
action = store.sendRequest;
|
action = store.sendRequest;
|
||||||
break;
|
break;
|
||||||
@ -133,26 +165,58 @@ export default class SMSVerification extends Component {
|
|||||||
return (<p>{ error }</p>);
|
return (<p>{ error }</p>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { method } = this.state;
|
||||||
|
if (phase === 0) {
|
||||||
|
const values = Object.values(methods);
|
||||||
|
const value = values.findIndex((v) => v.value === method);
|
||||||
|
return (
|
||||||
|
<RadioButtons
|
||||||
|
value={ value < 0 ? 0 : value }
|
||||||
|
values={ values }
|
||||||
|
onChange={ this.selectMethod }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
step,
|
step,
|
||||||
fee, number, isNumberValid, isVerified, hasRequested,
|
fee, isVerified, hasRequested,
|
||||||
requestTx, isCodeValid, confirmationTx,
|
requestTx, isCodeValid, confirmationTx,
|
||||||
setCode
|
setCode
|
||||||
} = this.props.store;
|
} = this.props.store;
|
||||||
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0:
|
|
||||||
return (
|
|
||||||
<p>Loading SMS Verification.</p>
|
|
||||||
);
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
const { setNumber, setConsentGiven } = this.props.store;
|
if (step === LOADING) {
|
||||||
|
return (<p>Loading verification data.</p>);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
return (
|
||||||
<GatherData
|
<GatherData
|
||||||
fee={ fee } isNumberValid={ isNumberValid }
|
method={ method } fields={ fields }
|
||||||
isVerified={ isVerified } hasRequested={ hasRequested }
|
fee={ fee } isVerified={ isVerified } hasRequested={ hasRequested }
|
||||||
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
|
setConsentGiven={ setConsentGiven }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -162,9 +226,19 @@ export default class SMSVerification extends Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
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 (
|
return (
|
||||||
<QueryCode
|
<QueryCode
|
||||||
number={ number } fee={ fee } isCodeValid={ isCodeValid }
|
receiver={ receiver }
|
||||||
|
hint={ hint }
|
||||||
|
isCodeValid={ isCodeValid }
|
||||||
setCode={ setCode }
|
setCode={ setCode }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -183,4 +257,8 @@ export default class SMSVerification extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectMethod = (choice, i) => {
|
||||||
|
this.setState({ method: choice.value });
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ import EditMeta from './EditMeta';
|
|||||||
import ExecuteContract from './ExecuteContract';
|
import ExecuteContract from './ExecuteContract';
|
||||||
import FirstRun from './FirstRun';
|
import FirstRun from './FirstRun';
|
||||||
import Shapeshift from './Shapeshift';
|
import Shapeshift from './Shapeshift';
|
||||||
import SMSVerification from './SMSVerification';
|
import Verification from './Verification';
|
||||||
import Transfer from './Transfer';
|
import Transfer from './Transfer';
|
||||||
import PasswordManager from './PasswordManager';
|
import PasswordManager from './PasswordManager';
|
||||||
import SaveContract from './SaveContract';
|
import SaveContract from './SaveContract';
|
||||||
@ -42,7 +42,7 @@ export {
|
|||||||
ExecuteContract,
|
ExecuteContract,
|
||||||
FirstRun,
|
FirstRun,
|
||||||
Shapeshift,
|
Shapeshift,
|
||||||
SMSVerification,
|
Verification,
|
||||||
Transfer,
|
Transfer,
|
||||||
PasswordManager,
|
PasswordManager,
|
||||||
LoadContract,
|
LoadContract,
|
||||||
|
@ -46,26 +46,26 @@ export default class Select extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
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 (
|
return (
|
||||||
<SelectField
|
<SelectField
|
||||||
className={ className }
|
|
||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
|
className={ className }
|
||||||
disabled={ disabled }
|
disabled={ disabled }
|
||||||
errorText={ error }
|
errorText={ error }
|
||||||
floatingLabelFixed
|
floatingLabelFixed
|
||||||
floatingLabelText={ label }
|
floatingLabelText={ label }
|
||||||
fullWidth
|
fullWidth
|
||||||
hintText={ hint }
|
hintText={ hint }
|
||||||
name={ NAME_ID }
|
|
||||||
id={ NAME_ID }
|
id={ NAME_ID }
|
||||||
underlineDisabledStyle={ UNDERLINE_DISABLED }
|
name={ NAME_ID }
|
||||||
underlineStyle={ UNDERLINE_NORMAL }
|
|
||||||
value={ value }
|
|
||||||
onBlur={ onBlur }
|
onBlur={ onBlur }
|
||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
onKeyDown={ onKeyDown }>
|
onKeyDown={ onKeyDown }
|
||||||
|
underlineDisabledStyle={ UNDERLINE_DISABLED }
|
||||||
|
underlineStyle={ UNDERLINE_NORMAL }
|
||||||
|
value={ value }>
|
||||||
{ children }
|
{ children }
|
||||||
</SelectField>
|
</SelectField>
|
||||||
);
|
);
|
||||||
|
@ -289,9 +289,8 @@ export default class TypedInput extends Component {
|
|||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={ bool }
|
key={ bool }
|
||||||
value={ bool }
|
|
||||||
label={ bool }
|
label={ bool }
|
||||||
>
|
value={ bool }>
|
||||||
{ bool }
|
{ bool }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
@ -299,19 +298,23 @@ export default class TypedInput extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
label={ label }
|
|
||||||
hint={ hint }
|
|
||||||
value={ value ? 'true' : 'false' }
|
|
||||||
error={ error }
|
error={ error }
|
||||||
|
hint={ hint }
|
||||||
|
label={ label }
|
||||||
onChange={ this.onChangeBool }
|
onChange={ this.onChangeBool }
|
||||||
>
|
value={
|
||||||
|
value
|
||||||
|
? 'true'
|
||||||
|
: 'false'
|
||||||
|
}>
|
||||||
{ boolitems }
|
{ boolitems }
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeBool = (event, _index, value) => {
|
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 = () => {
|
onEthTypeChange = () => {
|
||||||
|
70
js/src/ui/Form/TypedInput/typedInput.spec.js
Normal file
70
js/src/ui/Form/TypedInput/typedInput.spec.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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(
|
||||||
|
<ContextProvider api={ {} } muiTheme={ muiTheme } store={ {} }>
|
||||||
|
<TypedInput
|
||||||
|
{ ...props }
|
||||||
|
onChange={ onChange } />
|
||||||
|
</ContextProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ui/Form/TypedInput', () => {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -19,6 +19,8 @@ import { connect } from 'react-redux';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import ContractIcon from 'material-ui/svg-icons/action/code';
|
import ContractIcon from 'material-ui/svg-icons/action/code';
|
||||||
|
|
||||||
|
import { createIdentityImg } from '~/api/util/identity';
|
||||||
|
|
||||||
import styles from './identityIcon.css';
|
import styles from './identityIcon.css';
|
||||||
|
|
||||||
class IdentityIcon extends Component {
|
class IdentityIcon extends Component {
|
||||||
@ -29,12 +31,12 @@ class IdentityIcon extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
address: PropTypes.string,
|
address: PropTypes.string,
|
||||||
button: PropTypes.bool,
|
button: PropTypes.bool,
|
||||||
className: PropTypes.string,
|
|
||||||
center: PropTypes.bool,
|
center: PropTypes.bool,
|
||||||
padded: PropTypes.bool,
|
className: PropTypes.string,
|
||||||
inline: PropTypes.bool,
|
inline: PropTypes.bool,
|
||||||
tiny: PropTypes.bool,
|
images: PropTypes.object.isRequired,
|
||||||
images: PropTypes.object.isRequired
|
padded: PropTypes.bool,
|
||||||
|
tiny: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -75,7 +77,7 @@ class IdentityIcon extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
iconsrc: api.util.createIdentityImg(_address, scale)
|
iconsrc: createIdentityImg(_address, scale)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,16 +107,20 @@ class IdentityIcon extends Component {
|
|||||||
return (
|
return (
|
||||||
<ContractIcon
|
<ContractIcon
|
||||||
className={ classes }
|
className={ classes }
|
||||||
style={ { width: size, height: size, background: '#eee' } } />
|
style={ {
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
background: '#eee'
|
||||||
|
} } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={ classes }
|
className={ classes }
|
||||||
src={ iconsrc }
|
height={ size }
|
||||||
width={ size }
|
width={ size }
|
||||||
height={ size } />
|
src={ iconsrc } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import ContentSend from 'material-ui/svg-icons/content/send';
|
|||||||
import LockIcon from 'material-ui/svg-icons/action/lock';
|
import LockIcon from 'material-ui/svg-icons/action/lock';
|
||||||
import VerifyIcon from 'material-ui/svg-icons/action/verified-user';
|
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 { Actionbar, Button, Page } from '~/ui';
|
||||||
|
|
||||||
import shapeshiftBtn from '~/../assets/images/shapeshift-btn.png';
|
import shapeshiftBtn from '~/../assets/images/shapeshift-btn.png';
|
||||||
@ -32,7 +32,8 @@ import Header from './Header';
|
|||||||
import Transactions from './Transactions';
|
import Transactions from './Transactions';
|
||||||
import { setVisibleAccounts } from '~/redux/providers/personalActions';
|
import { setVisibleAccounts } from '~/redux/providers/personalActions';
|
||||||
|
|
||||||
import VerificationStore from '~/modals/SMSVerification/store';
|
import SMSVerificationStore from '~/modals/Verification/sms-store';
|
||||||
|
import EmailVerificationStore from '~/modals/Verification/email-store';
|
||||||
|
|
||||||
import styles from './account.css';
|
import styles from './account.css';
|
||||||
|
|
||||||
@ -72,15 +73,6 @@ class Account extends Component {
|
|||||||
if (prevAddress !== nextAddress) {
|
if (prevAddress !== nextAddress) {
|
||||||
this.setVisibleAccounts(nextProps);
|
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 () {
|
componentWillUnmount () {
|
||||||
@ -228,8 +220,9 @@ class Account extends Component {
|
|||||||
const { address } = this.props.params;
|
const { address } = this.props.params;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SMSVerification
|
<Verification
|
||||||
store={ store } account={ address }
|
store={ store } account={ address }
|
||||||
|
onSelectMethod={ this.selectVerificationMethod }
|
||||||
onClose={ this.onVerificationClose }
|
onClose={ this.onVerificationClose }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -303,6 +296,22 @@ class Account extends Component {
|
|||||||
this.setState({ showVerificationDialog: true });
|
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 = () => {
|
onVerificationClose = () => {
|
||||||
this.setState({ showVerificationDialog: false });
|
this.setState({ showVerificationDialog: false });
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ impl str::FromStr for SpecType {
|
|||||||
let spec = match s {
|
let spec = match s {
|
||||||
"frontier" | "homestead" | "mainnet" => SpecType::Mainnet,
|
"frontier" | "homestead" | "mainnet" => SpecType::Mainnet,
|
||||||
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
|
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
|
||||||
"morden" | "testnet" => SpecType::Testnet,
|
"morden" | "testnet" | "classic-testnet" => SpecType::Testnet,
|
||||||
"ropsten" => SpecType::Ropsten,
|
"ropsten" => SpecType::Ropsten,
|
||||||
"olympic" => SpecType::Olympic,
|
"olympic" => SpecType::Olympic,
|
||||||
"expanse" => SpecType::Expanse,
|
"expanse" => SpecType::Expanse,
|
||||||
@ -288,6 +288,8 @@ mod tests {
|
|||||||
assert_eq!(SpecType::Testnet, "morden".parse().unwrap());
|
assert_eq!(SpecType::Testnet, "morden".parse().unwrap());
|
||||||
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
|
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
|
||||||
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
|
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
|
||||||
|
assert_eq!(SpecType::Classic, "classic".parse().unwrap());
|
||||||
|
assert_eq!(SpecType::Testnet, "classic-testnet".parse().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -15,6 +15,7 @@ serde_json = "0.8"
|
|||||||
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
jsonrpc-http-server = { 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-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
|
jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
ethcore = { path = "../ethcore" }
|
ethcore = { path = "../ethcore" }
|
||||||
|
@ -42,6 +42,8 @@ extern crate fetch;
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate jsonrpc_macros;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate ethjson;
|
extern crate ethjson;
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! 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<Out>);
|
|
||||||
///
|
|
||||||
/// 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<Self> {
|
|
||||||
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<T: Default + Deserialize>(pub T);
|
|
||||||
|
|
||||||
/// A wrapper type for `jsonrpc_core`'s weakly-typed `Ready` struct.
|
|
||||||
pub struct Ready<T: Serialize> {
|
|
||||||
inner: ::jsonrpc_core::Ready,
|
|
||||||
_marker: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Serialize> From<::jsonrpc_core::Ready> for Ready<T> {
|
|
||||||
fn from(ready: ::jsonrpc_core::Ready) -> Self {
|
|
||||||
Ready { inner: ready, _marker: ::std::marker::PhantomData }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Serialize> Ready<T> {
|
|
||||||
/// Respond withthe asynchronous result.
|
|
||||||
pub fn ready(self, result: Result<T, Error>) {
|
|
||||||
self.inner.ready(result.map(to_value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper trait for synchronous RPC functions.
|
|
||||||
pub trait Wrap<B: Send + Sync + 'static> {
|
|
||||||
fn wrap_rpc(&self, base: &B, params: Params) -> Result<Value, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper trait for asynchronous RPC functions.
|
|
||||||
pub trait WrapAsync<B: Send + Sync + 'static> {
|
|
||||||
fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready);
|
|
||||||
}
|
|
||||||
|
|
||||||
// special impl for no parameters.
|
|
||||||
impl<B, OUT> Wrap<B> for fn(&B) -> Result<OUT, Error>
|
|
||||||
where B: Send + Sync + 'static, OUT: Serialize
|
|
||||||
{
|
|
||||||
fn wrap_rpc(&self, base: &B, params: Params) -> Result<Value, Error> {
|
|
||||||
::v1::helpers::params::expect_no_params(params)
|
|
||||||
.and_then(|()| (self)(base))
|
|
||||||
.map(to_value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B, OUT> WrapAsync<B> for fn(&B, Ready<OUT>)
|
|
||||||
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<BASE> for fn(&BASE, $($x,)+) -> Result<OUT, Error> {
|
|
||||||
fn wrap_rpc(&self, base: &BASE, params: Params) -> Result<Value, Error> {
|
|
||||||
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<BASE> for fn(&BASE, Ready<OUT>, $($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<B, OUT, T> Wrap<B> for fn(&B, Trailing<T>) -> Result<OUT, Error>
|
|
||||||
where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize
|
|
||||||
{
|
|
||||||
fn wrap_rpc(&self, base: &B, params: Params) -> Result<Value, Error> {
|
|
||||||
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<B, OUT, T> WrapAsync<B> for fn(&B, Ready<OUT>, Trailing<T>)
|
|
||||||
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<BASE> for fn(&BASE, $($x,)+ Trailing<TRAILING>) -> Result<OUT, Error> {
|
|
||||||
fn wrap_rpc(&self, base: &BASE, params: Params) -> Result<Value, Error> {
|
|
||||||
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<BASE> for fn(&BASE, Ready<OUT>, $($x,)+ Trailing<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);
|
|
@ -14,14 +14,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
pub mod auto_args;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
pub mod dispatch;
|
pub mod dispatch;
|
||||||
pub mod params;
|
|
||||||
pub mod block_import;
|
pub mod block_import;
|
||||||
|
|
||||||
mod poll_manager;
|
mod poll_manager;
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! 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<F1, F2>(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -27,6 +27,7 @@ use time::get_time;
|
|||||||
use ethsync::{SyncProvider};
|
use ethsync::{SyncProvider};
|
||||||
use ethcore::miner::{MinerService, ExternalMinerService};
|
use ethcore::miner::{MinerService, ExternalMinerService};
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
|
use jsonrpc_macros::Trailing;
|
||||||
use util::{H256, Address, FixedHash, U256, H64, Uint};
|
use util::{H256, Address, FixedHash, U256, H64, Uint};
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
use util::{FromHex, Mutex};
|
use util::{FromHex, Mutex};
|
||||||
@ -51,7 +52,6 @@ use v1::types::{
|
|||||||
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
||||||
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
||||||
use v1::helpers::block_import::is_major_importing;
|
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";
|
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ use ethcore::mode::Mode;
|
|||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
use jsonrpc_macros::Trailing;
|
||||||
use v1::traits::Parity;
|
use v1::traits::Parity;
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
Bytes, U256, H160, H256, H512,
|
Bytes, U256, H160, H256, H512,
|
||||||
@ -41,7 +42,6 @@ use v1::types::{
|
|||||||
};
|
};
|
||||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||||
use v1::helpers::dispatch::DEFAULT_MAC;
|
use v1::helpers::dispatch::DEFAULT_MAC;
|
||||||
use v1::helpers::auto_args::Trailing;
|
|
||||||
|
|
||||||
/// Parity implementation.
|
/// Parity implementation.
|
||||||
pub struct ParityClient<C, M, S: ?Sized> where
|
pub struct ParityClient<C, M, S: ?Sized> where
|
||||||
|
@ -26,7 +26,7 @@ use fetch::{Client as FetchClient, Fetch};
|
|||||||
use util::{Mutex, sha3};
|
use util::{Mutex, sha3};
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::auto_args::Ready;
|
use jsonrpc_macros::Ready;
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::traits::ParitySet;
|
use v1::traits::ParitySet;
|
||||||
use v1::types::{Bytes, H160, H256, U256};
|
use v1::types::{Bytes, H160, H256, U256};
|
||||||
|
@ -25,7 +25,7 @@ use ethcore::miner::MinerService;
|
|||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::auto_args::Ready;
|
use jsonrpc_macros::Ready;
|
||||||
use v1::helpers::{
|
use v1::helpers::{
|
||||||
errors, dispatch,
|
errors, dispatch,
|
||||||
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
||||||
|
@ -24,7 +24,7 @@ use ethcore::miner::MinerService;
|
|||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::auto_args::Ready;
|
use jsonrpc_macros::Ready;
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::helpers::dispatch;
|
use v1::helpers::dispatch;
|
||||||
use v1::traits::{EthSigning, ParitySigning};
|
use v1::traits::{EthSigning, ParitySigning};
|
||||||
|
@ -18,13 +18,15 @@
|
|||||||
|
|
||||||
use std::sync::{Weak, Arc};
|
use std::sync::{Weak, Arc};
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
|
use serde;
|
||||||
|
|
||||||
use rlp::{UntrustedRlp, View};
|
use rlp::{UntrustedRlp, View};
|
||||||
use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId};
|
use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId};
|
||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
||||||
|
|
||||||
use v1::traits::Traces;
|
use v1::traits::Traces;
|
||||||
use v1::helpers::{errors, CallRequest as CRequest};
|
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};
|
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||||
|
|
||||||
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
||||||
@ -35,6 +37,22 @@ fn to_call_analytics(flags: Vec<String>) -> 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<F1, F2>(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.
|
/// Traces api implementation.
|
||||||
pub struct TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
pub struct TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||||
client: Weak<C>,
|
client: Weak<C>,
|
||||||
|
@ -21,7 +21,7 @@ use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChange
|
|||||||
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
|
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
|
||||||
use v1::types::{H64, H160, H256, U256};
|
use v1::types::{H64, H160, H256, U256};
|
||||||
|
|
||||||
use v1::helpers::auto_args::{Trailing, Wrap};
|
use jsonrpc_macros::Trailing;
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Eth rpc interface.
|
/// Eth rpc interface.
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
//! Eth rpc interface.
|
//! Eth rpc interface.
|
||||||
|
|
||||||
use v1::helpers::auto_args::{WrapAsync, Ready};
|
use jsonrpc_macros::Ready;
|
||||||
|
|
||||||
use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction};
|
use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
//! Net rpc interface.
|
//! Net rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
use v1::helpers::auto_args::Wrap;
|
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Net rpc interface.
|
/// Net rpc interface.
|
||||||
pub trait Net {
|
pub trait Net {
|
||||||
|
@ -15,10 +15,12 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Parity-specific rpc interface.
|
//! Parity-specific rpc interface.
|
||||||
use jsonrpc_core::Error;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use v1::helpers::auto_args::{Wrap, Trailing};
|
|
||||||
|
use jsonrpc_core::Error;
|
||||||
|
use jsonrpc_macros::Trailing;
|
||||||
|
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
H160, H256, H512, U256, Bytes,
|
H160, H256, H512, U256, Bytes,
|
||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
//! Parity Accounts-related rpc interface.
|
//! Parity Accounts-related rpc interface.
|
||||||
use std::collections::BTreeMap;
|
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};
|
use v1::types::{H160, H256, DappId};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
//! Parity-specific rpc interface for operations altering the settings.
|
//! Parity-specific rpc interface for operations altering the settings.
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
use jsonrpc_macros::Ready;
|
||||||
|
|
||||||
use v1::helpers::auto_args::{Wrap, WrapAsync, Ready};
|
|
||||||
use v1::types::{Bytes, H160, H256, U256};
|
use v1::types::{Bytes, H160, H256, U256};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
//! ParitySigning rpc interface.
|
//! ParitySigning rpc interface.
|
||||||
use jsonrpc_core::Error;
|
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};
|
use v1::types::{U256, H160, H256, Bytes, ConfirmationResponse, TransactionRequest, Either};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
//! Personal rpc interface.
|
//! Personal rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
use v1::helpers::auto_args::Wrap;
|
|
||||||
use v1::types::{U128, H160, H256, TransactionRequest};
|
use v1::types::{U128, H160, H256, TransactionRequest};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
|
@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
//! RPC interface.
|
//! RPC interface.
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
|
||||||
|
|
||||||
use v1::helpers::auto_args::Wrap;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// RPC Interface.
|
/// RPC Interface.
|
||||||
pub trait Rpc {
|
pub trait Rpc {
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
//! Parity Signer-related rpc interface.
|
//! Parity Signer-related rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
use v1::helpers::auto_args::Wrap;
|
|
||||||
use v1::types::{U256, Bytes, TransactionModification, ConfirmationRequest, ConfirmationResponse};
|
use v1::types::{U256, Bytes, TransactionModification, ConfirmationRequest, ConfirmationResponse};
|
||||||
|
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Signer extension for confirmations rpc interface.
|
/// Signer extension for confirmations rpc interface.
|
||||||
pub trait Signer {
|
pub trait Signer {
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Traces specific rpc interface.
|
//! Traces specific rpc interface.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::{Params, Value, Error, IoDelegate};
|
||||||
|
|
||||||
/// Traces specific rpc interface.
|
/// Traces specific rpc interface.
|
||||||
pub trait Traces: Sized + Send + Sync + 'static {
|
pub trait Traces: Sized + Send + Sync + 'static {
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
//! Web3 rpc interface.
|
//! Web3 rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
use v1::helpers::auto_args::Wrap;
|
|
||||||
use v1::types::{H256, Bytes};
|
use v1::types::{H256, Bytes};
|
||||||
|
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Web3 rpc interface.
|
/// Web3 rpc interface.
|
||||||
pub trait Web3 {
|
pub trait Web3 {
|
||||||
|
Loading…
Reference in New Issue
Block a user