Merge branch 'master' into delete-accounts
This commit is contained in:
commit
609e8912d8
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -11,6 +11,7 @@ dependencies = [
|
||||
"ethcore 1.5.0",
|
||||
"ethcore-dapps 1.5.0",
|
||||
"ethcore-devtools 1.4.0",
|
||||
"ethcore-hash-fetch 1.5.0",
|
||||
"ethcore-io 1.5.0",
|
||||
"ethcore-ipc 1.4.0",
|
||||
"ethcore-ipc-codegen 1.4.0",
|
||||
@ -334,8 +335,8 @@ version = "1.5.0"
|
||||
dependencies = [
|
||||
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-devtools 1.4.0",
|
||||
"ethcore-hash-fetch 1.5.0",
|
||||
"ethcore-rpc 1.5.0",
|
||||
"ethcore-util 1.5.0",
|
||||
"fetch 0.1.0",
|
||||
@ -366,6 +367,18 @@ dependencies = [
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-hash-fetch"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-util 1.5.0",
|
||||
"fetch 0.1.0",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-io"
|
||||
version = "1.5.0"
|
||||
@ -1250,7 +1263,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#20e50a56709fbe3e39d0fea6cf31f48bd1da4bff"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#e005d40a1049dd1fd5d5543075f1fb66008c431c"
|
||||
dependencies = [
|
||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -43,6 +43,7 @@ ethcore-ipc-nano = { path = "ipc/nano" }
|
||||
ethcore-ipc = { path = "ipc/rpc" }
|
||||
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
||||
ethcore-logger = { path = "logger" }
|
||||
ethcore-hash-fetch = { path = "ethcore/hash-fetch" }
|
||||
rlp = { path = "util/rlp" }
|
||||
ethcore-stratum = { path = "stratum" }
|
||||
ethcore-dapps = { path = "dapps", optional = true }
|
||||
|
@ -20,20 +20,20 @@ url = "1.0"
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
ethabi = "0.2.2"
|
||||
linked-hash-map = "0.3"
|
||||
parity-dapps-glue = "1.4"
|
||||
mime = "0.2"
|
||||
mime_guess = "1.6.1"
|
||||
time = "0.1.35"
|
||||
serde_macros = { version = "0.8", optional = true }
|
||||
zip = { version = "0.1", default-features = false }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
ethcore-rpc = { path = "../rpc" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethcore-hash-fetch = { path = "../ethcore/hash-fetch" }
|
||||
fetch = { path = "../util/fetch" }
|
||||
parity-ui = { path = "./ui" }
|
||||
|
||||
mime_guess = { version = "1.6.1" }
|
||||
clippy = { version = "0.0.96", optional = true}
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -24,6 +24,7 @@ use std::io::{self, Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use hash_fetch::urlhint::{URLHintContract, URLHint, URLHintResult};
|
||||
|
||||
use hyper;
|
||||
use hyper::status::StatusCode;
|
||||
@ -37,7 +38,6 @@ use handlers::{ContentHandler, ContentFetcherHandler, ContentValidator};
|
||||
use endpoint::{Endpoint, EndpointPath, Handler};
|
||||
use apps::cache::{ContentCache, ContentStatus};
|
||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
||||
use apps::urlhint::{URLHintContract, URLHint, URLHintResult};
|
||||
|
||||
/// Limit of cached dapps/content
|
||||
const MAX_CACHED_DAPPS: usize = 20;
|
||||
@ -402,10 +402,11 @@ mod tests {
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use util::Bytes;
|
||||
use hash_fetch::urlhint::{URLHint, URLHintResult};
|
||||
|
||||
use apps::cache::ContentStatus;
|
||||
use endpoint::EndpointInfo;
|
||||
use page::LocalPageEndpoint;
|
||||
use apps::cache::ContentStatus;
|
||||
use apps::urlhint::{URLHint, URLHintResult};
|
||||
use super::ContentFetcher;
|
||||
|
||||
struct FakeResolver;
|
||||
|
@ -21,7 +21,6 @@ use parity_dapps::WebApp;
|
||||
|
||||
mod cache;
|
||||
mod fs;
|
||||
pub mod urlhint;
|
||||
pub mod fetcher;
|
||||
pub mod manifest;
|
||||
|
||||
|
@ -51,13 +51,13 @@ extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate zip;
|
||||
extern crate rand;
|
||||
extern crate ethabi;
|
||||
extern crate jsonrpc_core;
|
||||
extern crate jsonrpc_http_server;
|
||||
extern crate mime_guess;
|
||||
extern crate rustc_serialize;
|
||||
extern crate ethcore_rpc;
|
||||
extern crate ethcore_util as util;
|
||||
extern crate ethcore_hash_fetch as hash_fetch;
|
||||
extern crate linked_hash_map;
|
||||
extern crate fetch;
|
||||
extern crate parity_dapps_glue as parity_dapps;
|
||||
@ -84,12 +84,11 @@ mod url;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::apps::urlhint::ContractClient;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::net::SocketAddr;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use hash_fetch::urlhint::ContractClient;
|
||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
||||
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
||||
use ethcore_rpc::Extendable;
|
||||
@ -219,7 +218,7 @@ impl Server {
|
||||
) -> Result<Server, ServerError> {
|
||||
let panic_handler = Arc::new(Mutex::new(None));
|
||||
let authorization = Arc::new(authorization);
|
||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(apps::urlhint::URLHintContract::new(registrar), sync_status, signer_address.clone()));
|
||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(hash_fetch::urlhint::URLHintContract::new(registrar), sync_status, signer_address.clone()));
|
||||
let endpoints = Arc::new(apps::all_endpoints(dapps_path, signer_address.clone()));
|
||||
let cors_domains = Self::cors_domains(signer_address.clone());
|
||||
|
||||
|
@ -22,7 +22,7 @@ use env_logger::LogBuilder;
|
||||
|
||||
use ServerBuilder;
|
||||
use Server;
|
||||
use apps::urlhint::ContractClient;
|
||||
use hash_fetch::urlhint::ContractClient;
|
||||
use util::{Bytes, Address, Mutex, ToPretty};
|
||||
use devtools::http_client;
|
||||
|
||||
|
15
ethcore/hash-fetch/Cargo.toml
Normal file
15
ethcore/hash-fetch/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
description = "Fetching hash-addressed content."
|
||||
homepage = "https://ethcore.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-hash-fetch"
|
||||
version = "1.5.0"
|
||||
authors = ["Ethcore <admin@ethcore.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
rustc-serialize = "0.3"
|
||||
ethabi = "0.2.2"
|
||||
mime_guess = "1.6.1"
|
||||
fetch = { path = "../../util/fetch" }
|
||||
ethcore-util = { path = "../../util" }
|
114
ethcore/hash-fetch/src/client.rs
Normal file
114
ethcore/hash-fetch/src/client.rs
Normal file
@ -0,0 +1,114 @@
|
||||
// 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/>.
|
||||
|
||||
//! Hash-addressed content resolver & fetcher.
|
||||
|
||||
use std::{io, fs};
|
||||
use std::sync::Arc;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use util::{Mutex, H256, sha3};
|
||||
use fetch::{Fetch, FetchError, Client as FetchClient};
|
||||
|
||||
use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult};
|
||||
|
||||
/// API for fetching by hash.
|
||||
pub trait HashFetch {
|
||||
/// Fetch hash-addressed content.
|
||||
/// Parameters:
|
||||
/// 1. `hash` - content hash
|
||||
/// 2. `on_done` - callback function invoked when the content is ready (or there was error during fetch)
|
||||
///
|
||||
/// This function may fail immediately when fetch cannot be initialized or content cannot be resolved.
|
||||
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Hash-fetching error.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Hash could not be resolved to a valid content address.
|
||||
NoResolution,
|
||||
/// Downloaded content hash does not match.
|
||||
HashMismatch { expected: H256, got: H256 },
|
||||
/// IO Error while validating hash.
|
||||
IO(io::Error),
|
||||
/// Error during fetch.
|
||||
Fetch(FetchError),
|
||||
}
|
||||
|
||||
impl From<FetchError> for Error {
|
||||
fn from(error: FetchError) -> Self {
|
||||
Error::Fetch(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(error: io::Error) -> Self {
|
||||
Error::IO(error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Default Hash-fetching client using on-chain contract to resolve hashes to URLs.
|
||||
pub struct Client {
|
||||
contract: URLHintContract,
|
||||
fetch: Mutex<FetchClient>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// Creates new instance of the `Client` given on-chain contract client.
|
||||
pub fn new(contract: Arc<ContractClient>) -> Self {
|
||||
Client {
|
||||
contract: URLHintContract::new(contract),
|
||||
fetch: Mutex::new(FetchClient::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HashFetch for Client {
|
||||
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error> {
|
||||
debug!(target: "dapps", "Fetching: {:?}", hash);
|
||||
|
||||
let url = try!(
|
||||
self.contract.resolve(hash.to_vec()).map(|content| match content {
|
||||
URLHintResult::Dapp(dapp) => {
|
||||
dapp.url()
|
||||
},
|
||||
URLHintResult::Content(content) => {
|
||||
content.url
|
||||
},
|
||||
}).ok_or_else(|| Error::NoResolution)
|
||||
);
|
||||
|
||||
debug!(target: "dapps", "Resolved {:?} to {:?}. Fetching...", hash, url);
|
||||
|
||||
self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
|
||||
fn validate_hash(hash: H256, result: Result<PathBuf, FetchError>) -> Result<PathBuf, Error> {
|
||||
let path = try!(result);
|
||||
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
|
||||
let content_hash = try!(sha3(&mut file_reader));
|
||||
|
||||
if content_hash != hash {
|
||||
Err(Error::HashMismatch{ got: content_hash, expected: hash })
|
||||
} else {
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
|
||||
debug!(target: "dapps", "Content fetched, validating hash ({:?})", hash);
|
||||
on_done(validate_hash(hash, result))
|
||||
})).map_err(Into::into)
|
||||
}
|
||||
}
|
33
ethcore/hash-fetch/src/lib.rs
Normal file
33
ethcore/hash-fetch/src/lib.rs
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/>.
|
||||
|
||||
//! Hash-addressed content resolver & fetcher.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate rustc_serialize;
|
||||
extern crate mime_guess;
|
||||
extern crate ethabi;
|
||||
extern crate ethcore_util as util;
|
||||
extern crate fetch;
|
||||
|
||||
mod client;
|
||||
|
||||
pub mod urlhint;
|
||||
|
||||
pub use client::{HashFetch, Client};
|
@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! URLHint Contract
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
@ -24,15 +26,30 @@ use util::{Address, Bytes, Hashable};
|
||||
|
||||
const COMMIT_LEN: usize = 20;
|
||||
|
||||
/// RAW Contract interface.
|
||||
/// Should execute transaction using current blockchain state.
|
||||
pub trait ContractClient: Send + Sync {
|
||||
/// Get registrar address
|
||||
fn registrar(&self) -> Result<Address, String>;
|
||||
/// Call Contract
|
||||
fn call(&self, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
}
|
||||
|
||||
/// Github-hosted dapp.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct GithubApp {
|
||||
/// Github Account
|
||||
pub account: String,
|
||||
/// Github Repository
|
||||
pub repo: String,
|
||||
/// Commit on Github
|
||||
pub commit: [u8;COMMIT_LEN],
|
||||
/// Dapp owner address
|
||||
pub owner: Address,
|
||||
}
|
||||
|
||||
impl GithubApp {
|
||||
/// Returns URL of this Github-hosted dapp package.
|
||||
pub fn url(&self) -> String {
|
||||
// Since https fetcher doesn't support redirections we use direct link
|
||||
// format!("https://github.com/{}/{}/archive/{}.zip", self.account, self.repo, self.commit.to_hex())
|
||||
@ -53,22 +70,17 @@ impl GithubApp {
|
||||
}
|
||||
}
|
||||
|
||||
/// Hash-Addressed Content
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Content {
|
||||
/// URL of the content
|
||||
pub url: String,
|
||||
/// MIME type of the content
|
||||
pub mime: String,
|
||||
/// Content owner address
|
||||
pub owner: Address,
|
||||
}
|
||||
|
||||
/// RAW Contract interface.
|
||||
/// Should execute transaction using current blockchain state.
|
||||
pub trait ContractClient: Send + Sync {
|
||||
/// Get registrar address
|
||||
fn registrar(&self) -> Result<Address, String>;
|
||||
/// Call Contract
|
||||
fn call(&self, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
}
|
||||
|
||||
/// Result of resolving id to URL
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum URLHintResult {
|
||||
@ -84,6 +96,7 @@ pub trait URLHint {
|
||||
fn resolve(&self, id: Bytes) -> Option<URLHintResult>;
|
||||
}
|
||||
|
||||
/// `URLHintContract` API
|
||||
pub struct URLHintContract {
|
||||
urlhint: Contract,
|
||||
registrar: Contract,
|
||||
@ -91,9 +104,10 @@ pub struct URLHintContract {
|
||||
}
|
||||
|
||||
impl URLHintContract {
|
||||
/// Creates new `URLHintContract`
|
||||
pub fn new(client: Arc<ContractClient>) -> Self {
|
||||
let urlhint = Interface::load(include_bytes!("./urlhint.json")).expect("urlhint.json is valid ABI");
|
||||
let registrar = Interface::load(include_bytes!("./registrar.json")).expect("registrar.json is valid ABI");
|
||||
let urlhint = Interface::load(include_bytes!("../res/urlhint.json")).expect("urlhint.json is valid ABI");
|
||||
let registrar = Interface::load(include_bytes!("../res/registrar.json")).expect("registrar.json is valid ABI");
|
||||
|
||||
URLHintContract {
|
||||
urlhint: Contract::new(urlhint),
|
||||
@ -244,11 +258,6 @@ fn guess_mime_type(url: &str) -> Option<String> {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_guess_mime_type(url: &str) -> Option<String> {
|
||||
guess_mime_type(url)
|
||||
}
|
||||
|
||||
fn as_string<T: fmt::Debug>(e: T) -> String {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
@ -260,6 +269,7 @@ mod tests {
|
||||
use rustc_serialize::hex::FromHex;
|
||||
|
||||
use super::*;
|
||||
use super::guess_mime_type;
|
||||
use util::{Bytes, Address, Mutex, ToPretty};
|
||||
|
||||
struct FakeRegistrar {
|
||||
@ -390,10 +400,10 @@ mod tests {
|
||||
let url5 = "https://ethcore.io/parity.png";
|
||||
|
||||
|
||||
assert_eq!(test_guess_mime_type(url1), None);
|
||||
assert_eq!(test_guess_mime_type(url2), Some("image/png".into()));
|
||||
assert_eq!(test_guess_mime_type(url3), Some("image/png".into()));
|
||||
assert_eq!(test_guess_mime_type(url4), Some("image/jpeg".into()));
|
||||
assert_eq!(test_guess_mime_type(url5), Some("image/png".into()));
|
||||
assert_eq!(guess_mime_type(url1), None);
|
||||
assert_eq!(guess_mime_type(url2), Some("image/png".into()));
|
||||
assert_eq!(guess_mime_type(url3), Some("image/png".into()));
|
||||
assert_eq!(guess_mime_type(url4), Some("image/jpeg".into()));
|
||||
assert_eq!(guess_mime_type(url5), Some("image/png".into()));
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"generic": {
|
||||
"fields": 1,
|
||||
"rlp": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
|
||||
"fields": 2,
|
||||
"rlp": "0x200"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
|
304
ethcore/res/ethereum/ropsten.json
Normal file
304
ethcore/res/ethereum/ropsten.json
Normal file
@ -0,0 +1,304 @@
|
||||
{
|
||||
"name": "Ropsten",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
|
||||
"homesteadTransition": 0,
|
||||
"eip150Transition": 0,
|
||||
"eip155Transition": 10,
|
||||
"eip160Transition": 10,
|
||||
"eip161abcTransition": 10,
|
||||
"eip161dTransition": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x3"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x100000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x3535353535353535353535353535353535353535353535353535353535353535",
|
||||
"gasLimit": "0x1000000"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://a22f0977ce02653bf95e38730106356342df48b5222e2c2a1a6f9ef34769bf593bae9ca0a888cf60839edd52efc1b6e393c63a57d76f4c4fe14e641f1f9e637e@128.199.55.137:30303",
|
||||
"enode://012239fccf3ff1d92b036983a430cb6705c6528c96c0354413f8854802138e5135c084ab36e7c54efb621c46728df8c3a6f4c1db9bb48a1330efe3f82f2dd7a6@52.169.94.142:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "0", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000000": { "balance": "1" },
|
||||
"0000000000000000000000000000000000000005": { "balance": "1" },
|
||||
"0000000000000000000000000000000000000006": { "balance": "1" },
|
||||
"0000000000000000000000000000000000000007": { "balance": "1" },
|
||||
"0000000000000000000000000000000000000008": { "balance": "1" },
|
||||
"0000000000000000000000000000000000000009": { "balance": "1" },
|
||||
"000000000000000000000000000000000000000a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000000b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000000c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000000d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000000e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000000f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000010": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000011": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000012": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000013": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000014": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000015": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000016": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000017": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000018": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000019": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000001f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000020": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000021": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000022": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000023": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000024": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000025": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000026": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000027": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000028": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000029": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000002f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000030": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000031": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000032": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000033": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000034": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000035": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000036": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000037": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000038": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000039": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000003f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000040": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000041": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000042": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000043": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000044": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000045": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000046": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000047": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000048": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000049": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000004f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000050": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000051": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000052": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000053": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000054": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000055": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000056": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000057": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000058": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000059": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000005f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000060": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000061": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000062": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000063": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000064": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000065": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000066": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000067": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000068": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000069": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000006f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000070": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000071": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000072": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000073": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000074": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000075": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000076": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000077": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000078": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000079": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000007f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000080": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000081": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000082": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000083": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000084": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000085": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000086": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000087": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000088": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000089": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000008f": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000090": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000091": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000092": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000093": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000094": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000095": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000096": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000097": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000098": { "balance": "0" },
|
||||
"0000000000000000000000000000000000000099": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009a": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009b": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009c": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009d": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009e": { "balance": "0" },
|
||||
"000000000000000000000000000000000000009f": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000a9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000aa": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ab": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ac": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ad": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ae": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000af": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000b9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ba": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000bb": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000bc": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000bd": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000be": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000bf": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000c9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ca": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000cb": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000cc": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000cd": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ce": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000cf": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000d9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000da": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000db": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000dc": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000dd": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000de": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000df": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000e9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ea": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000eb": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ec": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ed": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ee": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ef": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f0": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f1": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f2": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f3": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f4": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f5": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f6": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f7": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f8": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000f9": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000fa": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000fb": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000fc": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000fd": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000fe": { "balance": "0" },
|
||||
"00000000000000000000000000000000000000ff": { "balance": "0" },
|
||||
"874b54a8bd152966d63f706bae1ffeb0411921e5": { "balance": "1000000000000000000000000000000" }
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x00006d6f7264656e",
|
||||
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
|
||||
"generic": {
|
||||
"fields": 0,
|
||||
"rlp": "0x0"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
|
@ -417,13 +417,13 @@ mod tests {
|
||||
let engine = Spec::new_test_round().engine;
|
||||
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
let mut step = UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
let time = UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
// Two authorities.
|
||||
let mut step = time - time % 2;
|
||||
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
let first_ok = engine.verify_block_seal(&header).is_ok();
|
||||
assert!(engine.verify_block_seal(&header).is_err());
|
||||
step = step + 1;
|
||||
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
let second_ok = engine.verify_block_seal(&header).is_ok();
|
||||
|
||||
assert!(first_ok ^ second_ok);
|
||||
assert!(engine.verify_block_seal(&header).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ pub fn new_transition_test() -> Spec { load(include_bytes!("../../res/ethereum/t
|
||||
/// Create a new Frontier main net chain spec without genesis accounts.
|
||||
pub fn new_mainnet_like() -> Spec { load(include_bytes!("../../res/ethereum/frontier_like_test.json")) }
|
||||
|
||||
/// Create a new Ropsten chain spec.
|
||||
pub fn new_ropsten() -> Spec { load(include_bytes!("../../res/ethereum/ropsten.json")) }
|
||||
|
||||
/// Create a new Morden chain spec.
|
||||
pub fn new_morden() -> Spec { load(include_bytes!("../../res/ethereum/morden.json")) }
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parity.js",
|
||||
"version": "0.2.56",
|
||||
"version": "0.2.62",
|
||||
"main": "release/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"author": "Parity Team <admin@parity.io>",
|
||||
|
@ -14,9 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { stringify } from 'querystring';
|
||||
import React from 'react';
|
||||
|
||||
export default (
|
||||
export const termsOfService = (
|
||||
<ul>
|
||||
<li>This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.</li>
|
||||
<li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li>
|
||||
@ -25,3 +26,18 @@ export default (
|
||||
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
|
||||
</ul>
|
||||
);
|
||||
|
||||
export const postToServer = (query) => {
|
||||
query = stringify(query);
|
||||
return fetch('https://sms-verification.parity.io/?' + query, {
|
||||
method: 'POST', mode: 'cors', cache: 'no-store'
|
||||
})
|
||||
.then((res) => {
|
||||
return res.json().then((data) => {
|
||||
if (res.ok) {
|
||||
return data.message;
|
||||
}
|
||||
throw new Error(data.message || 'unknown error');
|
||||
});
|
||||
});
|
||||
};
|
@ -14,8 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { stringify } from 'querystring';
|
||||
|
||||
export const checkIfVerified = (contract, account) => {
|
||||
return contract.instance.certified.call({}, [account]);
|
||||
};
|
||||
@ -35,18 +33,3 @@ export const checkIfRequested = (contract, account) => {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const postToServer = (query) => {
|
||||
query = stringify(query);
|
||||
return fetch('https://sms-verification.parity.io/?' + query, {
|
||||
method: 'POST', mode: 'cors', cache: 'no-store'
|
||||
})
|
||||
.then((res) => {
|
||||
return res.json().then((data) => {
|
||||
if (res.ok) {
|
||||
return data.message;
|
||||
}
|
||||
throw new Error(data.message || 'unknown error');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -105,7 +105,7 @@ export function attachInstances () {
|
||||
])
|
||||
.then(([registryAddress, netChain]) => {
|
||||
const registry = api.newContract(abis.registry, registryAddress).instance;
|
||||
isTest = netChain === 'morden' || netChain === 'testnet';
|
||||
isTest = ['morden', 'ropsten', 'testnet'].includes(netChain);
|
||||
|
||||
console.log(`contract was found at registry=${registryAddress}`);
|
||||
console.log(`running on ${netChain}, isTest=${isTest}`);
|
||||
|
17
js/src/dapps/dappreg.html
Normal file
17
js/src/dapps/dappreg.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="icon" href="/parity-logo-black-no-text.png" type="image/png">
|
||||
<title>Dapp Registry</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script src="vendor.js"></script>
|
||||
<script src="commons.js"></script>
|
||||
<script src="/parity-utils/parity.js"></script>
|
||||
<script src="dappreg.js"></script>
|
||||
</body>
|
||||
</html>
|
35
js/src/dapps/dappreg.js
Normal file
35
js/src/dapps/dappreg.js
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 ReactDOM from 'react-dom';
|
||||
import injectTapEventPlugin from 'react-tap-event-plugin';
|
||||
import { useStrict } from 'mobx';
|
||||
|
||||
injectTapEventPlugin();
|
||||
useStrict(true);
|
||||
|
||||
import Application from './dappreg/Application';
|
||||
|
||||
import '../../assets/fonts/Roboto/font.css';
|
||||
import '../../assets/fonts/RobotoMono/font.css';
|
||||
import './style.css';
|
||||
import './dappreg.html';
|
||||
|
||||
ReactDOM.render(
|
||||
<Application />,
|
||||
document.querySelector('#container')
|
||||
);
|
58
js/src/dapps/dappreg/Application/application.css
Normal file
58
js/src/dapps/dappreg/Application/application.css
Normal file
@ -0,0 +1,58 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.body {
|
||||
color: #333;
|
||||
background: #eee;
|
||||
padding: 4.5em 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.apps {
|
||||
background: #fff;
|
||||
border-radius: 0.5em;
|
||||
margin: 0 auto;
|
||||
max-width: 980px;
|
||||
padding: 1.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footer {
|
||||
font-size: 0.75em;
|
||||
margin: 1em;
|
||||
padding: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #44e;
|
||||
border-radius: 0 0 0.25em 0.25em;
|
||||
color: #fff;
|
||||
left: 0;
|
||||
padding: 1em;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 25;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding-top: 5em;
|
||||
font-size: 2em;
|
||||
color: #999;
|
||||
}
|
64
js/src/dapps/dappreg/Application/application.js
Normal file
64
js/src/dapps/dappreg/Application/application.js
Normal file
@ -0,0 +1,64 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DappsStore from '../dappsStore';
|
||||
|
||||
import ButtonBar from '../ButtonBar';
|
||||
import Dapp from '../Dapp';
|
||||
import ModalDelete from '../ModalDelete';
|
||||
import ModalRegister from '../ModalRegister';
|
||||
import ModalUpdate from '../ModalUpdate';
|
||||
import SelectDapp from '../SelectDapp';
|
||||
import Warning from '../Warning';
|
||||
import styles from './application.css';
|
||||
|
||||
@observer
|
||||
export default class Application extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
|
||||
render () {
|
||||
if (this.dappsStore.isLoading) {
|
||||
return (
|
||||
<div className={ styles.loading }>
|
||||
Loading application
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.body }>
|
||||
<div className={ styles.header }>
|
||||
DAPP REGISTRY, a global view of distributed applications available on the network. Putting the puzzle together.
|
||||
</div>
|
||||
<div className={ styles.apps }>
|
||||
<SelectDapp />
|
||||
<ButtonBar />
|
||||
<Dapp />
|
||||
</div>
|
||||
<div className={ styles.footer }>
|
||||
{ this.dappsStore.count } applications registered, { this.dappsStore.ownedCount } owned by user
|
||||
</div>
|
||||
<Warning />
|
||||
<ModalDelete />
|
||||
<ModalRegister />
|
||||
<ModalUpdate />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/Application/index.js
Normal file
17
js/src/dapps/dappreg/Application/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './application';
|
38
js/src/dapps/dappreg/Button/button.css
Normal file
38
js/src/dapps/dappreg/Button/button.css
Normal file
@ -0,0 +1,38 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.button {
|
||||
background: #44e;
|
||||
border: none;
|
||||
border-radius: 0.25em;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
margin: 1em 0.375em;
|
||||
opacity: 0.85;
|
||||
padding: 0.75em 2em;
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
background: #aaa;
|
||||
}
|
||||
|
||||
&[data-warning="true"] {
|
||||
background: #e44;
|
||||
}
|
||||
}
|
52
js/src/dapps/dappreg/Button/button.js
Normal file
52
js/src/dapps/dappreg/Button/button.js
Normal file
@ -0,0 +1,52 @@
|
||||
// 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, { Component, PropTypes } from 'react';
|
||||
|
||||
import styles from './button.css';
|
||||
|
||||
export default class Button extends Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
label: PropTypes.string.isRequired,
|
||||
warning: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, disabled, label, warning } = this.props;
|
||||
const classes = `${styles.button} ${className}`;
|
||||
|
||||
return (
|
||||
<button
|
||||
className={ classes }
|
||||
data-warning={ warning }
|
||||
disabled={ disabled }
|
||||
onClick={ this.onClick }>
|
||||
{ label }
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
onClick = (event) => {
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onClick(event);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/Button/index.js
Normal file
17
js/src/dapps/dappreg/Button/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './button';
|
21
js/src/dapps/dappreg/ButtonBar/buttonBar.css
Normal file
21
js/src/dapps/dappreg/ButtonBar/buttonBar.css
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
/* This file is part of Parity.
|
||||
/*
|
||||
/* Parity is free software: you can redistribute it and/or modify
|
||||
/* it under the terms of the GNU General Public License as published by
|
||||
/* the Free Software Foundation, either version 3 of the License, or
|
||||
/* (at your option) any later version.
|
||||
/*
|
||||
/* Parity is distributed in the hope that it will be useful,
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
/* GNU General Public License for more details.
|
||||
/*
|
||||
/* You should have received a copy of the GNU General Public License
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.buttonbar {
|
||||
text-align: center;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
101
js/src/dapps/dappreg/ButtonBar/buttonBar.js
Normal file
101
js/src/dapps/dappreg/ButtonBar/buttonBar.js
Normal file
@ -0,0 +1,101 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DappsStore from '../dappsStore';
|
||||
import ModalStore from '../modalStore';
|
||||
|
||||
import Button from '../Button';
|
||||
import styles from './buttonBar.css';
|
||||
|
||||
@observer
|
||||
export default class ButtonBar extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
modalStore = ModalStore.instance();
|
||||
|
||||
render () {
|
||||
let buttons = [];
|
||||
|
||||
if (this.dappsStore.isEditing || this.dappsStore.isNew) {
|
||||
buttons = [
|
||||
<Button
|
||||
key='cancel'
|
||||
label='Cancel'
|
||||
warning
|
||||
onClick={ this.onCancelClick } />,
|
||||
<Button
|
||||
key='save'
|
||||
label={ this.dappsStore.isNew ? 'Register' : 'Update' }
|
||||
disabled={ !this.dappsStore.canSave }
|
||||
onClick={ this.onSaveClick } />
|
||||
];
|
||||
} else {
|
||||
buttons = [
|
||||
<Button
|
||||
key='delete'
|
||||
label='Delete'
|
||||
warning
|
||||
disabled={ !this.dappsStore.currentApp.isOwner && !this.dappsStore.isContractOwner }
|
||||
onClick={ this.onDeleteClick } />,
|
||||
<Button
|
||||
key='edit'
|
||||
label='Edit'
|
||||
disabled={ !this.dappsStore.currentApp.isOwner }
|
||||
onClick={ this.onEditClick } />,
|
||||
<Button
|
||||
key='new'
|
||||
label='New'
|
||||
onClick={ this.onNewClick } />
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.buttonbar }>
|
||||
{ buttons }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onCancelClick = () => {
|
||||
if (this.dappsStore.isEditing) {
|
||||
this.dappsStore.setEditing(false);
|
||||
} else {
|
||||
this.dappsStore.setNew(false);
|
||||
}
|
||||
}
|
||||
|
||||
onDeleteClick = () => {
|
||||
this.modalStore.showDelete();
|
||||
}
|
||||
|
||||
onEditClick = () => {
|
||||
this.dappsStore.setEditing(true);
|
||||
}
|
||||
|
||||
onNewClick = () => {
|
||||
this.dappsStore.setNew(true);
|
||||
}
|
||||
|
||||
onSaveClick = () => {
|
||||
if (this.dappsStore.isEditing) {
|
||||
this.modalStore.showUpdate();
|
||||
} else {
|
||||
this.modalStore.showRegister();
|
||||
}
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/ButtonBar/index.js
Normal file
17
js/src/dapps/dappreg/ButtonBar/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './buttonBar';
|
19
js/src/dapps/dappreg/Dapp/dapp.css
Normal file
19
js/src/dapps/dappreg/Dapp/dapp.css
Normal file
@ -0,0 +1,19 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.app {
|
||||
}
|
162
js/src/dapps/dappreg/Dapp/dapp.js
Normal file
162
js/src/dapps/dappreg/Dapp/dapp.js
Normal file
@ -0,0 +1,162 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { api } from '../parity';
|
||||
import DappsStore from '../dappsStore';
|
||||
|
||||
import Input from '../Input';
|
||||
import SelectAccount from '../SelectAccount';
|
||||
import styles from './dapp.css';
|
||||
|
||||
@observer
|
||||
export default class Dapp extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
|
||||
render () {
|
||||
const app = this.dappsStore.isNew || this.dappsStore.isEditing
|
||||
? this.dappsStore.wipApp
|
||||
: this.dappsStore.currentApp;
|
||||
|
||||
return (
|
||||
<div className={ styles.app }>
|
||||
{ this.dappsStore.isNew ? this.renderOwnerSelect(app) : this.renderOwnerStatic(app) }
|
||||
{ this.renderInputs(app) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderInputs (app) {
|
||||
if (this.dappsStore.isNew) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
this.renderHashInput(app, 'image', 'Image hash, as generated by Githubhint', true),
|
||||
this.renderHashInput(app, 'manifest', 'Manifest hash, as generated by Githubhint'),
|
||||
this.renderHashInput(app, 'content', 'Content hash, as generated by Githubhint')
|
||||
];
|
||||
}
|
||||
|
||||
renderOwnerSelect (app) {
|
||||
const overlayImage = (
|
||||
<img
|
||||
className={ styles.overlayImage }
|
||||
src={ api.util.createIdentityImg(this.dappsStore.currentAccount.address, 4) } />
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
hint={ this.dappsStore.currentAccount.address }
|
||||
label='Owner, select the application owner and editor'
|
||||
overlay={ overlayImage }>
|
||||
<SelectAccount />
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
renderOwnerStatic (app) {
|
||||
const overlayImage = (
|
||||
<img
|
||||
className={ styles.overlayImage }
|
||||
src={ api.util.createIdentityImg(app.owner, 4) } />
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
hint={ app.owner }
|
||||
label='Owner, the application owner and editor'
|
||||
overlay={ overlayImage }>
|
||||
<input value={ app.ownerName } readOnly />
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
renderHashInput (app, type, label, withImage = false) {
|
||||
const onChange = (event) => this.onChangeHash(event, type);
|
||||
const hash = app[`${type}Hash`];
|
||||
|
||||
let overlayImage = null;
|
||||
if (withImage && hash) {
|
||||
overlayImage = (
|
||||
<img
|
||||
className={ styles.overlayImage }
|
||||
src={ `/api/content/${hash.substr(2)}` } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
hint={ app[`${type}Error`] || app[`${type}Url`] || '...' }
|
||||
label={ label }
|
||||
key={ `${type}Edit` }
|
||||
overlay={ overlayImage }>
|
||||
<input
|
||||
value={ app[`${type}Hash`] || '' }
|
||||
data-dirty={ app[`${type}Changed`] }
|
||||
data-error={ !!app[`${type}Error`] }
|
||||
readOnly={ !this.dappsStore.isEditing && !this.dappsStore.isNew }
|
||||
onChange={ onChange } />
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
onChangeHash (event, type) {
|
||||
if (!this.dappsStore.isNew && !this.dappsStore.isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hash = event.target.value;
|
||||
let changed = false;
|
||||
let url = null;
|
||||
|
||||
if (this.dappsStore.isNew) {
|
||||
if (hash && hash.length) {
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (this.dappsStore.currentApp[`${type}Hash`] !== hash) {
|
||||
changed = true;
|
||||
} else {
|
||||
url = this.dappsStore.currentApp[`${type}Url`];
|
||||
}
|
||||
}
|
||||
|
||||
this.dappsStore.editWip({
|
||||
[`${type}Changed`]: changed,
|
||||
[`${type}Error`]: null,
|
||||
[`${type}Hash`]: hash,
|
||||
[`${type}Url`]: changed ? 'Resolving url from hash' : url
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
if (hash.length) {
|
||||
this.dappsStore
|
||||
.lookupHash(hash)
|
||||
.then((url) => {
|
||||
this.dappsStore.editWip({
|
||||
[`${type}Error`]: url ? null : 'Unable to resolve url',
|
||||
[`${type}Url`]: url
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.dappsStore.editWip({ [`${type}Url`]: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/Dapp/index.js
Normal file
17
js/src/dapps/dappreg/Dapp/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './dapp';
|
17
js/src/dapps/dappreg/Input/index.js
Normal file
17
js/src/dapps/dappreg/Input/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './input';
|
92
js/src/dapps/dappreg/Input/input.css
Normal file
92
js/src/dapps/dappreg/Input/input.css
Normal file
@ -0,0 +1,92 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.input {
|
||||
position: relative;
|
||||
|
||||
input, select {
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
border: 4px solid rgba(223, 223, 223, 0.85);
|
||||
border-radius: 0.25em;
|
||||
box-sizing: border-box;
|
||||
color: #333;
|
||||
font-size: 1em;
|
||||
margin: 0.25em 0 0.25em 0;
|
||||
padding: 0.5em 0.5em 1.5em 0.5em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
padding-bottom: 1.5em;
|
||||
|
||||
&[data-dirty="true"] {
|
||||
background: rgba(255, 255, 203, 0.85);
|
||||
border-color: rgba(203, 203, 151, 0.85);
|
||||
}
|
||||
|
||||
&[data-error="true"] {
|
||||
background: rgba(255, 223, 223, 0.85) !important;
|
||||
border-color: rgba(223, 191, 191, 0.85) !important;
|
||||
}
|
||||
|
||||
&[readonly] {
|
||||
background: rgba(239, 239, 239, 0.85);
|
||||
border-color: rgba(223, 223, 223, 0.85);
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
color: #888;
|
||||
display: block;
|
||||
font-size: 0.75em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
select {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
height: 58px;
|
||||
|
||||
&[disabled] {
|
||||
background: rgba(239, 239, 239, 0.85);
|
||||
border-color: rgba(223, 223, 223, 0.85);
|
||||
}
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: #888;
|
||||
display: block;
|
||||
font-size: 0.75em;
|
||||
position: absolute;
|
||||
right: 52px;
|
||||
text-align: right;
|
||||
top: 52px;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
}
|
47
js/src/dapps/dappreg/Input/input.js
Normal file
47
js/src/dapps/dappreg/Input/input.js
Normal file
@ -0,0 +1,47 @@
|
||||
// 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, { Component, PropTypes } from 'react';
|
||||
|
||||
import styles from './input.css';
|
||||
|
||||
export default class Input extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
hint: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
overlay: PropTypes.node
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, hint, label, overlay } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.input }>
|
||||
<label>
|
||||
{ label }
|
||||
</label>
|
||||
{ children }
|
||||
<div className={ styles.hint }>
|
||||
{ hint }
|
||||
</div>
|
||||
<div className={ styles.overlay }>
|
||||
{ overlay }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/Modal/index.js
Normal file
17
js/src/dapps/dappreg/Modal/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './modal';
|
116
js/src/dapps/dappreg/Modal/modal.css
Normal file
116
js/src/dapps/dappreg/Modal/modal.css
Normal file
@ -0,0 +1,116 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.modal {
|
||||
.body {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
z-index: 50;
|
||||
|
||||
.dialog {
|
||||
background: #fff;
|
||||
border-radius: 0 0 0.25em 0.25em;
|
||||
margin: 0 auto;
|
||||
max-width: 840px;
|
||||
text-align: left;
|
||||
|
||||
.content {
|
||||
line-height: 1.5em;
|
||||
padding: 2em;
|
||||
text-align: center;
|
||||
|
||||
.section {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
&.error {
|
||||
color: #f44;
|
||||
}
|
||||
}
|
||||
|
||||
.section+.section {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 0.5em 1.625em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #44e;
|
||||
color: #fff;
|
||||
opacity: 0.85;
|
||||
padding: 1em;
|
||||
|
||||
&.error {
|
||||
background: #e44;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
background: rgba(204, 204, 204, 0.7);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 49;
|
||||
}
|
||||
}
|
||||
|
||||
.account {
|
||||
div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.hint {
|
||||
display: block !important;
|
||||
color: #888;
|
||||
font-size: 0.75em;
|
||||
margin-top: -0.5em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heading {
|
||||
color: #888;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.light {
|
||||
color: #888;
|
||||
}
|
66
js/src/dapps/dappreg/Modal/modal.js
Normal file
66
js/src/dapps/dappreg/Modal/modal.js
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import styles from './modal.css';
|
||||
|
||||
export default class Modal extends Component {
|
||||
static propTypes = {
|
||||
buttons: PropTypes.node,
|
||||
children: PropTypes.node,
|
||||
error: PropTypes.object,
|
||||
header: PropTypes.string
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, buttons, error, header } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.modal }>
|
||||
<div className={ styles.overlay } />
|
||||
<div className={ styles.body }>
|
||||
<div className={ styles.dialog }>
|
||||
<div className={ `${styles.header} ${error ? styles.error : ''}` }>
|
||||
{ header }
|
||||
</div>
|
||||
<div className={ styles.content }>
|
||||
{ error ? this.renderError() : children }
|
||||
</div>
|
||||
<div className={ styles.footer }>
|
||||
{ buttons }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderError () {
|
||||
const { error } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
Your operation failed to complete sucessfully. The following error was returned:
|
||||
</div>
|
||||
<div className={ `${styles.section} ${styles.error}` }>
|
||||
{ error.toString() }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/ModalDelete/index.js
Normal file
17
js/src/dapps/dappreg/ModalDelete/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './modalDelete';
|
159
js/src/dapps/dappreg/ModalDelete/modalDelete.js
Normal file
159
js/src/dapps/dappreg/ModalDelete/modalDelete.js
Normal file
@ -0,0 +1,159 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { api } from '../parity';
|
||||
import DappsStore from '../dappsStore';
|
||||
import ModalStore from '../modalStore';
|
||||
|
||||
import Button from '../Button';
|
||||
import Modal from '../Modal';
|
||||
|
||||
import styles from '../Modal/modal.css';
|
||||
|
||||
const HEADERS = [
|
||||
'Error During Deletion',
|
||||
'Confirm Application Deletion',
|
||||
'Waiting for Signer Confirmation',
|
||||
'Waiting for Transaction Receipt',
|
||||
'Deletion Completed'
|
||||
];
|
||||
const STEP_ERROR = 0;
|
||||
const STEP_CONFIRM = 1;
|
||||
const STEP_SIGNER = 2;
|
||||
const STEP_TXRECEIPT = 3;
|
||||
const STEP_DONE = 4;
|
||||
|
||||
@observer
|
||||
export default class ModalDelete extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
modalStore = ModalStore.instance();
|
||||
|
||||
render () {
|
||||
if (!this.modalStore.showingDelete) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
buttons={ this.renderButtons() }
|
||||
error={ this.modalStore.errorDelete }
|
||||
header={ HEADERS[this.modalStore.stepDelete] }>
|
||||
{ this.renderStep() }
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
renderButtons () {
|
||||
switch (this.modalStore.stepDelete) {
|
||||
case STEP_ERROR:
|
||||
case STEP_DONE:
|
||||
return [
|
||||
<Button
|
||||
key='close'
|
||||
label='Close'
|
||||
onClick={ this.onClickClose } />
|
||||
];
|
||||
case STEP_CONFIRM:
|
||||
return [
|
||||
<Button
|
||||
key='cancel'
|
||||
label='No, Cancel'
|
||||
onClick={ this.onClickClose } />,
|
||||
<Button
|
||||
key='delete'
|
||||
label='Yes, Delete'
|
||||
warning
|
||||
onClick={ this.onClickYes } />
|
||||
];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStep () {
|
||||
switch (this.modalStore.stepDelete) {
|
||||
case STEP_CONFIRM:
|
||||
return this.renderStepConfirm();
|
||||
case STEP_SIGNER:
|
||||
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
|
||||
case STEP_TXRECEIPT:
|
||||
return this.renderStepWait('Waiting for the transaction receipt from the network');
|
||||
case STEP_DONE:
|
||||
return this.renderStepCompleted();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStepCompleted () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
Your application has been removed from the registry.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStepConfirm () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
You are about to remove a distributed application from the registry, the details of this application is given below. Removal does not return any fees, however the application will not be available to users anymore.
|
||||
</div>
|
||||
<div className={ styles.section }>
|
||||
<div className={ styles.heading }>
|
||||
Owner account
|
||||
</div>
|
||||
<div className={ styles.account }>
|
||||
<img src={ api.util.createIdentityImg(this.dappsStore.currentApp.owner, 3) } />
|
||||
<div>{ this.dappsStore.currentApp.ownerName }</div>
|
||||
<div className={ styles.address }>{ this.dappsStore.currentApp.owner }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={ styles.section }>
|
||||
<div className={ styles.heading }>
|
||||
Application identifier
|
||||
</div>
|
||||
<div>
|
||||
{ this.dappsStore.currentApp.id }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStepWait (waitingFor) {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
{ waitingFor }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.modalStore.hideDelete();
|
||||
}
|
||||
|
||||
onClickYes = () => {
|
||||
this.modalStore.doDelete();
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/ModalRegister/index.js
Normal file
17
js/src/dapps/dappreg/ModalRegister/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './modalRegister';
|
159
js/src/dapps/dappreg/ModalRegister/modalRegister.js
Normal file
159
js/src/dapps/dappreg/ModalRegister/modalRegister.js
Normal file
@ -0,0 +1,159 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { api } from '../parity';
|
||||
import DappsStore from '../dappsStore';
|
||||
import ModalStore from '../modalStore';
|
||||
|
||||
import Button from '../Button';
|
||||
import Modal from '../Modal';
|
||||
|
||||
import styles from '../Modal/modal.css';
|
||||
|
||||
const HEADERS = [
|
||||
'Error During Registration',
|
||||
'Confirm Application Registration',
|
||||
'Waiting for Signer Confirmation',
|
||||
'Waiting for Transaction Receipt',
|
||||
'Registration Completed'
|
||||
];
|
||||
const STEP_ERROR = 0;
|
||||
const STEP_CONFIRM = 1;
|
||||
const STEP_SIGNER = 2;
|
||||
const STEP_TXRECEIPT = 3;
|
||||
const STEP_DONE = 4;
|
||||
|
||||
@observer
|
||||
export default class ModalRegister extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
modalStore = ModalStore.instance();
|
||||
|
||||
render () {
|
||||
if (!this.modalStore.showingRegister) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
buttons={ this.renderButtons() }
|
||||
error={ this.modalStore.errorRegister }
|
||||
header={ HEADERS[this.modalStore.stepRegister] }>
|
||||
{ this.renderStep() }
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
renderButtons () {
|
||||
switch (this.modalStore.stepRegister) {
|
||||
case STEP_ERROR:
|
||||
case STEP_DONE:
|
||||
return [
|
||||
<Button
|
||||
key='close'
|
||||
label='Close'
|
||||
onClick={ this.onClickClose } />
|
||||
];
|
||||
case STEP_CONFIRM:
|
||||
return [
|
||||
<Button
|
||||
key='cancel'
|
||||
label='No, Cancel'
|
||||
onClick={ this.onClickClose } />,
|
||||
<Button
|
||||
key='register'
|
||||
label='Yes, Register'
|
||||
warning
|
||||
onClick={ this.onClickConfirmYes } />
|
||||
];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStep () {
|
||||
switch (this.modalStore.stepRegister) {
|
||||
case STEP_CONFIRM:
|
||||
return this.renderStepConfirm();
|
||||
case STEP_SIGNER:
|
||||
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
|
||||
case STEP_TXRECEIPT:
|
||||
return this.renderStepWait('Waiting for the transaction receipt from the network');
|
||||
case STEP_DONE:
|
||||
return this.renderStepCompleted();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStepCompleted () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
Your application has been registered in the registry.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStepConfirm () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
You are about to register a new distributed application on the network, the details of this application is given below. This will require a non-refundable fee of { api.util.fromWei(this.dappsStore.fee).toFormat(3) }<small>ETH</small>.
|
||||
</div>
|
||||
<div className={ styles.section }>
|
||||
<div className={ styles.heading }>
|
||||
Selected owner account
|
||||
</div>
|
||||
<div className={ styles.account }>
|
||||
<img src={ api.util.createIdentityImg(this.dappsStore.currentAccount.address, 3) } />
|
||||
<div>{ this.dappsStore.currentAccount.name }</div>
|
||||
<div className={ styles.hint }>{ this.dappsStore.currentAccount.address }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={ styles.section }>
|
||||
<div className={ styles.heading }>
|
||||
Unique assigned application identifier
|
||||
</div>
|
||||
<div>
|
||||
{ this.dappsStore.wipApp.id }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStepWait (waitingFor) {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
{ waitingFor }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.modalStore.hideRegister();
|
||||
}
|
||||
|
||||
onClickConfirmYes = () => {
|
||||
this.modalStore.doRegister();
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/ModalUpdate/index.js
Normal file
17
js/src/dapps/dappreg/ModalUpdate/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './modalUpdate';
|
169
js/src/dapps/dappreg/ModalUpdate/modalUpdate.js
Normal file
169
js/src/dapps/dappreg/ModalUpdate/modalUpdate.js
Normal file
@ -0,0 +1,169 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DappsStore from '../dappsStore';
|
||||
import ModalStore from '../modalStore';
|
||||
|
||||
import Button from '../Button';
|
||||
import Modal from '../Modal';
|
||||
|
||||
import styles from '../Modal/modal.css';
|
||||
|
||||
const HEADERS = [
|
||||
'Error During Update',
|
||||
'Confirm Application Update',
|
||||
'Waiting for Signer Confirmation',
|
||||
'Waiting for Transaction Receipt',
|
||||
'Update Completed'
|
||||
];
|
||||
const STEP_ERROR = 0;
|
||||
const STEP_CONFIRM = 1;
|
||||
const STEP_SIGNER = 2;
|
||||
const STEP_TXRECEIPT = 3;
|
||||
const STEP_DONE = 4;
|
||||
|
||||
@observer
|
||||
export default class ModalUpdate extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
modalStore = ModalStore.instance();
|
||||
|
||||
render () {
|
||||
if (!this.modalStore.showingUpdate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
buttons={ this.renderButtons() }
|
||||
error={ this.modalStore.errorUpdate }
|
||||
header={ HEADERS[this.modalStore.stepUpdate] }>
|
||||
{ this.renderStep() }
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
renderButtons () {
|
||||
switch (this.modalStore.stepUpdate) {
|
||||
case STEP_ERROR:
|
||||
case STEP_DONE:
|
||||
return [
|
||||
<Button
|
||||
key='close'
|
||||
label='Close'
|
||||
onClick={ this.onClickClose } />
|
||||
];
|
||||
case STEP_CONFIRM:
|
||||
return [
|
||||
<Button
|
||||
key='cancel'
|
||||
label='No, Cancel'
|
||||
onClick={ this.onClickClose } />,
|
||||
<Button
|
||||
key='delete'
|
||||
label='Yes, Update'
|
||||
warning
|
||||
onClick={ this.onClickYes } />
|
||||
];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStep () {
|
||||
switch (this.modalStore.stepUpdate) {
|
||||
case STEP_CONFIRM:
|
||||
return this.renderStepConfirm();
|
||||
case STEP_SIGNER:
|
||||
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
|
||||
case STEP_TXRECEIPT:
|
||||
return this.renderStepWait('Waiting for the transaction receipt from the network');
|
||||
case STEP_DONE:
|
||||
return this.renderStepCompleted();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderStepCompleted () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
Your application metadata has been updated in the registry.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStepConfirm () {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
You are about to update the application details in the registry, the details of these updates are given below. Please note that each update will generate a seperate transaction.
|
||||
</div>
|
||||
<div className={ styles.section }>
|
||||
<div className={ styles.heading }>
|
||||
Application identifier
|
||||
</div>
|
||||
<div>
|
||||
{ this.dappsStore.wipApp.id }
|
||||
</div>
|
||||
</div>
|
||||
{ this.renderChanges() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderChanges () {
|
||||
return ['content', 'image', 'manifest']
|
||||
.filter((type) => this.dappsStore.wipApp[`${type}Changed`])
|
||||
.map((type) => {
|
||||
return (
|
||||
<div className={ styles.section } key={ `${type}Update` }>
|
||||
<div className={ styles.heading }>
|
||||
Updates to { type } hash
|
||||
</div>
|
||||
<div>
|
||||
<div>{ this.dappsStore.wipApp[`${type}Hash`] || '(removed)' }</div>
|
||||
<div className={ styles.hint }>
|
||||
{ this.dappsStore.wipApp[`${type}Url`] || 'current url to be removed from registry' }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
renderStepWait (waitingFor) {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
{ waitingFor }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.modalStore.hideUpdate();
|
||||
}
|
||||
|
||||
onClickYes = () => {
|
||||
this.modalStore.doUpdate();
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/SelectAccount/index.js
Normal file
17
js/src/dapps/dappreg/SelectAccount/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './selectAccount';
|
49
js/src/dapps/dappreg/SelectAccount/selectAccount.js
Normal file
49
js/src/dapps/dappreg/SelectAccount/selectAccount.js
Normal file
@ -0,0 +1,49 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DappsStore from '../dappsStore';
|
||||
|
||||
@observer
|
||||
export default class SelectAccount extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
|
||||
render () {
|
||||
return (
|
||||
<select
|
||||
value={ this.dappsStore.currentAccount.address }
|
||||
onChange={ this.onSelect }>
|
||||
{ this.renderOptions() }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
renderOptions () {
|
||||
return this.dappsStore.accounts.map((account) => {
|
||||
return (
|
||||
<option value={ account.address } key={ account.address }>
|
||||
{ account.name }
|
||||
</option>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onSelect = (event) => {
|
||||
this.dappsStore.setCurrentAccount(event.target.value);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/SelectDapp/index.js
Normal file
17
js/src/dapps/dappreg/SelectDapp/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './selectDapp';
|
76
js/src/dapps/dappreg/SelectDapp/selectDapp.js
Normal file
76
js/src/dapps/dappreg/SelectDapp/selectDapp.js
Normal file
@ -0,0 +1,76 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DappsStore from '../dappsStore';
|
||||
|
||||
import Input from '../Input';
|
||||
|
||||
@observer
|
||||
export default class SelectDapp extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
|
||||
render () {
|
||||
if (this.dappsStore.isNew) {
|
||||
return (
|
||||
<Input
|
||||
hint='...'
|
||||
label='Application Id, the unique assigned identifier'>
|
||||
<input value={ this.dappsStore.wipApp.id } readOnly />
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
let overlayImg = null;
|
||||
if (this.dappsStore.currentApp.imageHash) {
|
||||
overlayImg = (
|
||||
<img src={ `/api/content/${this.dappsStore.currentApp.imageHash.substr(2)}` } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
hint={ this.dappsStore.currentApp.id }
|
||||
label='Application, the actual application details to show below'
|
||||
overlay={ overlayImg }>
|
||||
<select
|
||||
disabled={ this.dappsStore.isEditing }
|
||||
value={ this.dappsStore.currentApp.id }
|
||||
onChange={ this.onSelect }>
|
||||
{ this.renderOptions() }
|
||||
</select>
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
renderOptions () {
|
||||
return this.dappsStore.apps.map((app) => {
|
||||
return (
|
||||
<option
|
||||
value={ app.id }
|
||||
key={ app.id }>
|
||||
{ app.name }
|
||||
</option>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onSelect = (event) => {
|
||||
this.dappsStore.setCurrentApp(event.target.value);
|
||||
}
|
||||
}
|
17
js/src/dapps/dappreg/Warning/index.js
Normal file
17
js/src/dapps/dappreg/Warning/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/>.
|
||||
|
||||
export default from './warning';
|
36
js/src/dapps/dappreg/Warning/warning.css
Normal file
36
js/src/dapps/dappreg/Warning/warning.css
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.warning {
|
||||
background: #f44;
|
||||
border-top-right-radius: 0.25em;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
left: 0;
|
||||
line-height: 1.5em;
|
||||
opacity: 1;
|
||||
padding: 1.5em;
|
||||
position: fixed;
|
||||
max-width: 540px;
|
||||
z-index: 100;
|
||||
|
||||
div+div {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
}
|
51
js/src/dapps/dappreg/Warning/warning.js
Normal file
51
js/src/dapps/dappreg/Warning/warning.js
Normal file
@ -0,0 +1,51 @@
|
||||
// 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, { Component } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { api } from '../parity';
|
||||
import DappsStore from '../dappsStore';
|
||||
import ModalStore from '../modalStore';
|
||||
|
||||
import styles from './warning.css';
|
||||
|
||||
@observer
|
||||
export default class Warning extends Component {
|
||||
dappsStore = DappsStore.instance();
|
||||
modalStore = ModalStore.instance();
|
||||
|
||||
render () {
|
||||
if (!this.modalStore.showingWarning) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.warning } onClick={ this.onClose }>
|
||||
<div>
|
||||
WARNING: Registering a dapp is for developers only. Please ensure you understand the steps needed to develop and deploy applications, should you wish to use this dapp for anything apart from queries.
|
||||
</div>
|
||||
<div>
|
||||
A non-refundable fee of { api.util.fromWei(this.dappsStore.fee).toFormat(3) }<small>ETH</small> is required for any registration.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onClose = () => {
|
||||
this.modalStore.hideWarning();
|
||||
}
|
||||
}
|
482
js/src/dapps/dappreg/dappsStore.js
Normal file
482
js/src/dapps/dappreg/dappsStore.js
Normal file
@ -0,0 +1,482 @@
|
||||
// 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 BigNumber from 'bignumber.js';
|
||||
import { action, computed, observable, transaction } from 'mobx';
|
||||
|
||||
import * as abis from '../../contracts/abi';
|
||||
import builtins from '../../views/Dapps/builtin.json';
|
||||
|
||||
import { api } from './parity';
|
||||
|
||||
let instance = null;
|
||||
|
||||
export default class DappsStore {
|
||||
@observable accounts = [];
|
||||
@observable addresses = [];
|
||||
@observable apps = [];
|
||||
@observable contractOwner = null;
|
||||
@observable currentAccount = null;
|
||||
@observable currentApp = null;
|
||||
@observable count = 0;
|
||||
@observable fee = new BigNumber(0);
|
||||
@observable isContractOwner = false;
|
||||
@observable isEditing = false;
|
||||
@observable isLoading = true;
|
||||
@observable isNew = false;
|
||||
@observable wipApp = null;
|
||||
|
||||
_startTime = Date.now();
|
||||
|
||||
constructor () {
|
||||
this._loadDapps();
|
||||
}
|
||||
|
||||
static instance () {
|
||||
if (!instance) {
|
||||
instance = new DappsStore();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@computed get canSave () {
|
||||
const app = this.wipApp;
|
||||
|
||||
const hasError = app.contentError || app.imageError || app.manifestError;
|
||||
const isDirty = this.isNew || app.contentChanged || app.imageChanged || app.manifestChanged;
|
||||
const isEditMode = this.isEditing || this.isNew;
|
||||
|
||||
return isEditMode && isDirty && !hasError;
|
||||
}
|
||||
|
||||
@computed get isCurrentEditable () {
|
||||
return !!this.accounts.find((account) => account.address === this.currentApp.owner);
|
||||
}
|
||||
|
||||
@computed get ownedCount () {
|
||||
return (this.apps.filter((app) => app.isOwner) || []).length;
|
||||
}
|
||||
|
||||
@action copyToWip = () => {
|
||||
let wipApp;
|
||||
|
||||
if (this.isNew) {
|
||||
wipApp = {
|
||||
id: api.util.sha3(`${this._startTime}_${Date.now()}`),
|
||||
contentHash: null,
|
||||
contentUrl: null,
|
||||
imageHash: null,
|
||||
imageUrl: null,
|
||||
manifestHash: null,
|
||||
manifestUrl: null
|
||||
};
|
||||
} else {
|
||||
const app = this.currentApp;
|
||||
|
||||
wipApp = {
|
||||
id: app.id,
|
||||
contentHash: app.contentHash,
|
||||
contentUrl: app.contentUrl,
|
||||
imageHash: app.imageHash,
|
||||
imageUrl: app.imageUrl,
|
||||
manifestHash: app.manifestHash,
|
||||
manifestUrl: app.manifestUrl,
|
||||
owner: app.owner,
|
||||
ownerName: app.ownerName
|
||||
};
|
||||
}
|
||||
|
||||
this.wipApp = Object.assign(wipApp, {
|
||||
contentChanged: false,
|
||||
contentError: null,
|
||||
imageChanged: false,
|
||||
imageError: null,
|
||||
manifestChanged: false,
|
||||
manifestError: null
|
||||
});
|
||||
|
||||
return this.wipApp;
|
||||
}
|
||||
|
||||
@action editWip = (details) => {
|
||||
if (this.isNew || this.isEditing) {
|
||||
transaction(() => {
|
||||
Object
|
||||
.keys(details)
|
||||
.forEach((key) => {
|
||||
this.wipApp[key] = details[key];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return this.wipApp;
|
||||
}
|
||||
|
||||
@action sortApps = (apps = this.apps) => {
|
||||
transaction(() => {
|
||||
const ownApps = apps
|
||||
.filter((app) => app.isOwner)
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const otherApps = apps
|
||||
.filter((app) => !app.isOwner)
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
this.apps = ownApps.concat(otherApps);
|
||||
this.currentApp = this.apps[0];
|
||||
});
|
||||
}
|
||||
|
||||
@action setApps = (apps) => {
|
||||
this.sortApps(apps.filter((app) => {
|
||||
const bnid = new BigNumber(app.id);
|
||||
return bnid.gt(0);
|
||||
}));
|
||||
|
||||
return this.apps;
|
||||
}
|
||||
|
||||
@action _addApp = (app) => {
|
||||
transaction(() => {
|
||||
this.setApps(this.apps.concat([app]));
|
||||
this.setCurrentApp(app.id);
|
||||
});
|
||||
}
|
||||
|
||||
@action addApp = (appId, account) => {
|
||||
this
|
||||
._loadDapp({
|
||||
id: appId,
|
||||
isOwner: true,
|
||||
name: `- ${appId}`,
|
||||
owner: account.address,
|
||||
ownerName: account.name
|
||||
})
|
||||
.then(this._addApp);
|
||||
}
|
||||
|
||||
@action refreshApp = (appId) => {
|
||||
this._loadDapp(this.apps.find((app) => app.id === appId));
|
||||
}
|
||||
|
||||
@action removeApp = (appId) => {
|
||||
this.setApps(this.apps.filter((app) => app.id !== appId));
|
||||
}
|
||||
|
||||
@action setAppInfo = (app, info) => {
|
||||
transaction(() => {
|
||||
Object.keys(info).forEach((key) => {
|
||||
app[key] = info[key];
|
||||
});
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@action setAccounts = (accountsInfo) => {
|
||||
transaction(() => {
|
||||
this.addresses = Object
|
||||
.keys(accountsInfo)
|
||||
.map((address) => {
|
||||
const account = accountsInfo[address];
|
||||
account.address = address;
|
||||
return account;
|
||||
});
|
||||
|
||||
this.accounts = this.addresses.filter((account) => account.uuid);
|
||||
this.currentAccount = this.accounts[0];
|
||||
});
|
||||
|
||||
return this.accounts;
|
||||
}
|
||||
|
||||
@action setContractOwner = (contractOwner) => {
|
||||
transaction(() => {
|
||||
this.contractOwner = contractOwner;
|
||||
this.isContractOwner = !!this.accounts.find((account) => account.address === contractOwner);
|
||||
});
|
||||
return contractOwner;
|
||||
}
|
||||
|
||||
@action setCurrentApp = (id) => {
|
||||
this.currentApp = this.apps.find((app) => app.id === id);
|
||||
return this.currentApp;
|
||||
}
|
||||
|
||||
@action setCurrentAccount = (address) => {
|
||||
this.currentAccount = this.accounts.find((account) => account.address === address);
|
||||
return this.currentAccount;
|
||||
}
|
||||
|
||||
@action setCount = (count) => {
|
||||
this.count = count;
|
||||
return count;
|
||||
}
|
||||
|
||||
@action setEditing = (mode) => {
|
||||
transaction(() => {
|
||||
this.isEditing = mode;
|
||||
this.copyToWip();
|
||||
});
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
@action setFee = (fee) => {
|
||||
this.fee = fee;
|
||||
return fee;
|
||||
}
|
||||
|
||||
@action setLoading = (loading) => {
|
||||
this.isLoading = loading;
|
||||
return loading;
|
||||
}
|
||||
|
||||
@action setNew = (mode) => {
|
||||
transaction(() => {
|
||||
this.isNew = mode;
|
||||
this.copyToWip();
|
||||
});
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
lookupHash (hash) {
|
||||
return this._retrieveUrl(hash);
|
||||
}
|
||||
|
||||
_getCount () {
|
||||
return this._instanceReg
|
||||
.count.call()
|
||||
.then((count) => {
|
||||
this.setCount(count.toNumber());
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:getCount', error);
|
||||
});
|
||||
}
|
||||
|
||||
_getFee () {
|
||||
return this._instanceReg
|
||||
.fee.call()
|
||||
.then(this.setFee)
|
||||
.catch((error) => {
|
||||
console.error('Store:getFee', error);
|
||||
});
|
||||
}
|
||||
|
||||
_getOwner () {
|
||||
return this._instanceReg
|
||||
.owner.call()
|
||||
.then(this.setContractOwner)
|
||||
.catch((error) => {
|
||||
console.error('Store:getOwner', error);
|
||||
});
|
||||
}
|
||||
|
||||
_loadDapps () {
|
||||
return this._loadRegistry()
|
||||
.then(() => Promise.all([
|
||||
this._attachContracts(),
|
||||
this._loadAccounts()
|
||||
]))
|
||||
.then(() => Promise.all([
|
||||
this._getCount(),
|
||||
this._getFee(),
|
||||
this._getOwner()
|
||||
]))
|
||||
.then(() => {
|
||||
const promises = [];
|
||||
|
||||
for (let index = 0; index < this.count; index++) {
|
||||
promises.push(this._instanceReg.at.call({}, [index]));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then((appsInfo) => {
|
||||
return Promise.all(
|
||||
this
|
||||
.setApps(appsInfo.map(([appId, owner]) => {
|
||||
const isOwner = !!this.accounts.find((account) => account.address === owner);
|
||||
const account = this.addresses.find((account) => account.address === owner);
|
||||
const id = api.util.bytesToHex(appId);
|
||||
|
||||
return {
|
||||
id,
|
||||
owner,
|
||||
ownerName: account ? account.name : owner,
|
||||
isOwner,
|
||||
name: `- ${id}`
|
||||
};
|
||||
}))
|
||||
.map(this._loadDapp)
|
||||
);
|
||||
})
|
||||
.then(() => {
|
||||
this.sortApps();
|
||||
this.setLoading(this.count === 0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:loadDapps', error);
|
||||
});
|
||||
}
|
||||
|
||||
_loadDapp = (app) => {
|
||||
return Promise
|
||||
.all([
|
||||
this._loadMeta(app.id, 'CONTENT'),
|
||||
this._loadMeta(app.id, 'IMG'),
|
||||
this._loadMeta(app.id, 'MANIFEST')
|
||||
])
|
||||
.then(([contentHash, imageHash, manifestHash]) => {
|
||||
return Promise
|
||||
.all([
|
||||
this._retrieveUrl(contentHash),
|
||||
this._retrieveUrl(imageHash),
|
||||
this._retrieveUrl(manifestHash)
|
||||
])
|
||||
.then(([contentUrl, imageUrl, manifestUrl]) => {
|
||||
return this
|
||||
._loadManifest(app.id, manifestHash)
|
||||
.then((manifest) => {
|
||||
this.setAppInfo(app, {
|
||||
manifest,
|
||||
manifestHash,
|
||||
manifestUrl,
|
||||
contentHash,
|
||||
contentUrl,
|
||||
imageHash,
|
||||
imageUrl,
|
||||
name: (manifest && manifest.name) || `- ${app.id}`
|
||||
});
|
||||
|
||||
return app;
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:loadDapp', error);
|
||||
});
|
||||
}
|
||||
|
||||
_loadMeta (appId, key) {
|
||||
return this._instanceReg
|
||||
.meta.call({}, [appId, key])
|
||||
.then((meta) => {
|
||||
const hash = api.util.bytesToHex(meta);
|
||||
const bnhash = new BigNumber(hash);
|
||||
|
||||
return bnhash.gt(0)
|
||||
? hash
|
||||
: null;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:loadMeta', error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
_loadManifest (appId, manifestHash) {
|
||||
const builtin = builtins.find((app) => app.id === appId);
|
||||
|
||||
if (builtin) {
|
||||
return Promise.resolve(builtin);
|
||||
} else if (!manifestHash) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
return fetch(`/api/content/${manifestHash.substr(2)}/`, { redirect: 'follow', mode: 'cors' })
|
||||
.then((response) => {
|
||||
return response.ok
|
||||
? response.json()
|
||||
: null;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:loadManifest', error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
_retrieveUrl (urlHash) {
|
||||
if (!urlHash) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
return this._instanceGhh
|
||||
.entries.call({}, [urlHash])
|
||||
.then(([repo, _commit, owner]) => {
|
||||
const bnowner = new BigNumber(owner);
|
||||
|
||||
if (bnowner.eq(0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const commit = api.util.bytesToHex(_commit);
|
||||
const bncommit = new BigNumber(commit);
|
||||
|
||||
if (bncommit.eq(0)) {
|
||||
return repo;
|
||||
} else {
|
||||
return `https://codeload.github.com/${repo}/zip/${commit.substr(2)}`;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:retriveUrl', error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
_loadAccounts () {
|
||||
return api.parity
|
||||
.accounts()
|
||||
.then(this.setAccounts)
|
||||
.catch((error) => {
|
||||
console.error('Store:loadAccounts', error);
|
||||
});
|
||||
}
|
||||
|
||||
_loadRegistry () {
|
||||
return api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
console.log(`the registry was found at ${registryAddress}`);
|
||||
this._registry = api.newContract(abis.registry, registryAddress).instance;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:loadRegistry', error);
|
||||
});
|
||||
}
|
||||
|
||||
_attachContracts () {
|
||||
return Promise
|
||||
.all([
|
||||
this._registry.getAddress.call({}, [api.util.sha3('dappreg'), 'A']),
|
||||
this._registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A'])
|
||||
])
|
||||
.then(([dappregAddress, ghhAddress]) => {
|
||||
console.log(`dappreg was found at ${dappregAddress}`);
|
||||
this._contractReg = api.newContract(abis.dappreg, dappregAddress);
|
||||
this._instanceReg = this._contractReg.instance;
|
||||
console.log(`githubhint was found at ${ghhAddress}`);
|
||||
this._contractGhh = api.newContract(abis.githubhint, ghhAddress);
|
||||
this._instanceGhh = this._contractGhh.instance;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Store:attachContract', error);
|
||||
});
|
||||
}
|
||||
}
|
266
js/src/dapps/dappreg/modalStore.js
Normal file
266
js/src/dapps/dappreg/modalStore.js
Normal file
@ -0,0 +1,266 @@
|
||||
// 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 { action, observable, transaction } from 'mobx';
|
||||
|
||||
import { trackRequest } from './parity';
|
||||
import DappsStore from './dappsStore';
|
||||
|
||||
let instance = null;
|
||||
|
||||
export default class ModalStore {
|
||||
@observable errorDelete = null;
|
||||
@observable errorRegister = null;
|
||||
@observable errorUpdate = null;
|
||||
@observable stepDelete = 0;
|
||||
@observable stepRegister = 0;
|
||||
@observable stepUpdate = 0;
|
||||
@observable showingDelete = false;
|
||||
@observable showingRegister = false;
|
||||
@observable showingUpdate = false;
|
||||
@observable showingWarning = true;
|
||||
|
||||
_dappsStore = DappsStore.instance();
|
||||
|
||||
static instance () {
|
||||
if (!instance) {
|
||||
instance = new ModalStore();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@action setDeleteError (error) {
|
||||
transaction(() => {
|
||||
this.setDeleteStep(0);
|
||||
this.errorDelete = error;
|
||||
});
|
||||
}
|
||||
|
||||
@action setDeleteStep (step) {
|
||||
this.stepDelete = step;
|
||||
}
|
||||
|
||||
@action showDelete () {
|
||||
transaction(() => {
|
||||
this.setDeleteStep(1);
|
||||
this.errorDelete = null;
|
||||
this.showingDelete = true;
|
||||
});
|
||||
}
|
||||
|
||||
@action hideDelete () {
|
||||
this.showingDelete = false;
|
||||
}
|
||||
|
||||
@action setRegisterError (error) {
|
||||
transaction(() => {
|
||||
this.setRegisterStep(0);
|
||||
this.errorRegister = error;
|
||||
});
|
||||
}
|
||||
|
||||
@action setRegisterStep (step) {
|
||||
this.stepRegister = step;
|
||||
}
|
||||
|
||||
@action showRegister () {
|
||||
transaction(() => {
|
||||
this.setRegisterStep(1);
|
||||
this.errorRegister = null;
|
||||
this.showingRegister = true;
|
||||
});
|
||||
}
|
||||
|
||||
@action hideRegister () {
|
||||
transaction(() => {
|
||||
this._dappsStore.setEditing(false);
|
||||
this._dappsStore.setNew(false);
|
||||
this.showingRegister = false;
|
||||
});
|
||||
}
|
||||
|
||||
@action setUpdateError (error) {
|
||||
transaction(() => {
|
||||
this.setUpdateStep(0);
|
||||
this.errorUpdate = error;
|
||||
});
|
||||
}
|
||||
|
||||
@action setUpdateStep (step) {
|
||||
this.stepUpdate = step;
|
||||
}
|
||||
|
||||
@action showUpdate () {
|
||||
transaction(() => {
|
||||
this.setUpdateStep(1);
|
||||
this.errorUpdate = null;
|
||||
this.showingUpdate = true;
|
||||
});
|
||||
}
|
||||
|
||||
@action hideUpdate () {
|
||||
transaction(() => {
|
||||
this._dappsStore.setEditing(false);
|
||||
this._dappsStore.setNew(false);
|
||||
this.showingUpdate = false;
|
||||
});
|
||||
}
|
||||
|
||||
@action hideWarning () {
|
||||
this.showingWarning = false;
|
||||
}
|
||||
|
||||
doDelete () {
|
||||
this.setDeleteStep(2);
|
||||
|
||||
const appId = this._dappsStore.currentApp.id;
|
||||
const values = [appId];
|
||||
const options = {
|
||||
from: this._dappsStore.currentApp.isOwner ? this._dappsStore.currentApp.owner : this._dappsStore.contractOwner
|
||||
};
|
||||
|
||||
console.log('ModalStore:doDelete', `performing deletion for ${appId} from ${options.from}`);
|
||||
|
||||
this._dappsStore._instanceReg
|
||||
.unregister.estimateGas(options, values)
|
||||
.then((gas) => {
|
||||
const newGas = gas.mul(1.2);
|
||||
|
||||
console.log('ModalStore:doDelete', `gas estimated as ${gas.toFormat(0)}, setting to ${newGas.toFormat(0)}`);
|
||||
|
||||
options.gas = newGas.toFixed(0);
|
||||
|
||||
const request = this._dappsStore._instanceReg.unregister.postTransaction(options, values);
|
||||
const statusCallback = (error, status) => {
|
||||
if (error) {
|
||||
} else if (status.signerRequestId) {
|
||||
} else if (status.transactionHash) {
|
||||
this.setDeleteStep(3);
|
||||
} else if (status.transactionReceipt) {
|
||||
this.setDeleteStep(4);
|
||||
this._dappsStore.removeApp(appId);
|
||||
}
|
||||
};
|
||||
|
||||
return trackRequest(request, statusCallback);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('ModalStore:doDelete', error);
|
||||
this.setDeleteError(error);
|
||||
});
|
||||
}
|
||||
|
||||
doRegister () {
|
||||
this.setRegisterStep(2);
|
||||
|
||||
const appId = this._dappsStore.wipApp.id;
|
||||
const values = [appId];
|
||||
const options = {
|
||||
from: this._dappsStore.currentAccount.address,
|
||||
value: this._dappsStore.fee
|
||||
};
|
||||
|
||||
console.log('ModalStore:doRegister', `performing registration for ${appId} from ${this._dappsStore.currentAccount.address}`);
|
||||
|
||||
this._dappsStore._instanceReg
|
||||
.register.estimateGas(options, values)
|
||||
.then((gas) => {
|
||||
const newGas = gas.mul(1.2);
|
||||
|
||||
console.log('ModalStore:doRegister', `gas estimated as ${gas.toFormat(0)}, setting to ${newGas.toFormat(0)}`);
|
||||
|
||||
options.gas = newGas.toFixed(0);
|
||||
|
||||
const request = this._dappsStore._instanceReg.register.postTransaction(options, values);
|
||||
const statusCallback = (error, status) => {
|
||||
if (error) {
|
||||
} else if (status.signerRequestId) {
|
||||
} else if (status.transactionHash) {
|
||||
this.setRegisterStep(3);
|
||||
} else if (status.transactionReceipt) {
|
||||
this.setRegisterStep(4);
|
||||
this._dappsStore.addApp(appId, this._dappsStore.currentAccount);
|
||||
}
|
||||
};
|
||||
|
||||
return trackRequest(request, statusCallback);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('ModalStore:doRegister', error);
|
||||
this.setRegisterError(error);
|
||||
});
|
||||
}
|
||||
|
||||
doUpdate () {
|
||||
this.setUpdateStep(2);
|
||||
|
||||
const appId = this._dappsStore.wipApp.id;
|
||||
const options = {
|
||||
from: this._dappsStore.wipApp.owner
|
||||
};
|
||||
const types = {
|
||||
'content': 'CONTENT',
|
||||
'image': 'IMG',
|
||||
'manifest': 'MANIFEST'
|
||||
};
|
||||
const values = Object
|
||||
.keys(types)
|
||||
.filter((type) => this._dappsStore.wipApp[`${type}Changed`])
|
||||
.map((type) => {
|
||||
return [appId, types[type], this._dappsStore.wipApp[`${type}Hash`] || '0x0'];
|
||||
});
|
||||
|
||||
console.log('ModalStore:doUpdate', `performing updates for ${appId} from ${options.from}`);
|
||||
|
||||
Promise
|
||||
.all(values.map((value) => this._dappsStore._instanceReg.setMeta.estimateGas(options, value)))
|
||||
.then((gas) => {
|
||||
const newGas = gas.map((gas) => gas.mul(1.2));
|
||||
|
||||
gas.forEach((gas, index) => {
|
||||
console.log('ModalStore:doUpdate', `${values[index][1]} gas estimated as ${gas.toFormat(0)}, setting to ${newGas[index].toFormat(0)}`);
|
||||
});
|
||||
|
||||
const statusCallback = (error, status) => {
|
||||
if (error) {
|
||||
} else if (status.signerRequestId) {
|
||||
} else if (status.transactionHash) {
|
||||
this.setUpdateStep(3);
|
||||
} else if (status.transactionReceipt) {
|
||||
this.setUpdateStep(4);
|
||||
}
|
||||
};
|
||||
|
||||
return Promise.all(
|
||||
newGas.map((gas, index) => {
|
||||
return trackRequest(
|
||||
this._dappsStore._instanceReg.setMeta.postTransaction(
|
||||
Object.assign(options, { gas: gas.toFixed(0) }), values[index]
|
||||
), statusCallback
|
||||
);
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(() => {
|
||||
this._dappsStore.refreshApp(appId);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('ModalStore:doUpdate', error);
|
||||
this.setUpdateError(error);
|
||||
});
|
||||
}
|
||||
}
|
53
js/src/dapps/dappreg/parity.js
Normal file
53
js/src/dapps/dappreg/parity.js
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
const { api } = window.parity;
|
||||
|
||||
function trackRequest (requestPromise, statusCallback) {
|
||||
return requestPromise
|
||||
.then((signerRequestId) => {
|
||||
console.log('trackRequest', `posted to signer with requestId ${signerRequestId.toString()}`);
|
||||
statusCallback(null, { signerRequestId });
|
||||
|
||||
return api.pollMethod('parity_checkRequest', signerRequestId);
|
||||
})
|
||||
.then((transactionHash) => {
|
||||
console.log('trackRequest', `received transaction hash ${transactionHash}`);
|
||||
statusCallback(null, { transactionHash });
|
||||
|
||||
return api.pollMethod('eth_getTransactionReceipt', transactionHash, (receipt) => {
|
||||
if (!receipt || !receipt.blockNumber || receipt.blockNumber.eq(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
})
|
||||
.then((transactionReceipt) => {
|
||||
console.log('trackRequest', 'received transaction receipt', transactionReceipt);
|
||||
statusCallback(null, { transactionReceipt });
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('trackRequest', error);
|
||||
statusCallback(error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
api,
|
||||
trackRequest
|
||||
};
|
@ -77,7 +77,7 @@ export default class Lookup extends Component {
|
||||
label='Lookup'
|
||||
primary
|
||||
icon={ <SearchIcon /> }
|
||||
onClick={ this.onLookupClick }
|
||||
onTouchTap={ this.onLookupClick }
|
||||
/>
|
||||
</div>
|
||||
<CardText>{ output }</CardText>
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { sha3, toWei } from '../parity.js';
|
||||
import { sha3, api } from '../parity.js';
|
||||
|
||||
const alreadyQueued = (queue, action, name) =>
|
||||
!!queue.find((entry) => entry.action === action && entry.name === name);
|
||||
@ -29,6 +29,8 @@ export const reserve = (name) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
const fee = state.fee;
|
||||
|
||||
if (!contract || !account) return;
|
||||
if (alreadyQueued(state.names.queue, 'reserve', name)) return;
|
||||
const reserve = contract.functions.find((f) => f.name === 'reserve');
|
||||
@ -36,19 +38,28 @@ export const reserve = (name) => (dispatch, getState) => {
|
||||
name = name.toLowerCase();
|
||||
const options = {
|
||||
from: account.address,
|
||||
value: toWei(1).toString()
|
||||
value: fee
|
||||
};
|
||||
const values = [ sha3(name) ];
|
||||
|
||||
dispatch(reserveStart(name));
|
||||
|
||||
reserve.estimateGas(options, values)
|
||||
.then((gas) => {
|
||||
options.gas = gas.mul(1.2).toFixed(0);
|
||||
return reserve.postTransaction(options, values);
|
||||
})
|
||||
.then((data) => {
|
||||
.then((requestId) => {
|
||||
return api.pollMethod('parity_checkRequest', requestId);
|
||||
})
|
||||
.then((txhash) => {
|
||||
dispatch(reserveSuccess(name));
|
||||
}).catch((err) => {
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err && err.type === 'REQUEST_REJECTED') {
|
||||
return dispatch(reserveFail(name));
|
||||
}
|
||||
|
||||
console.error(`could not reserve ${name}`);
|
||||
if (err) console.error(err.stack);
|
||||
dispatch(reserveFail(name));
|
||||
@ -79,9 +90,17 @@ export const drop = (name) => (dispatch, getState) => {
|
||||
options.gas = gas.mul(1.2).toFixed(0);
|
||||
return drop.postTransaction(options, values);
|
||||
})
|
||||
.then((data) => {
|
||||
.then((requestId) => {
|
||||
return api.pollMethod('parity_checkRequest', requestId);
|
||||
})
|
||||
.then((txhash) => {
|
||||
dispatch(dropSuccess(name));
|
||||
}).catch((err) => {
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err && err.type === 'REQUEST_REJECTED') {
|
||||
dispatch(reserveFail(name));
|
||||
}
|
||||
|
||||
console.error(`could not drop ${name}`);
|
||||
if (err) console.error(err.stack);
|
||||
dispatch(reserveFail(name));
|
||||
|
@ -86,6 +86,22 @@ export default class Names extends Component {
|
||||
name: ''
|
||||
};
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const nextQueue = nextProps.queue;
|
||||
const prevQueue = this.props.queue;
|
||||
|
||||
if (nextQueue.length > prevQueue.length) {
|
||||
const newQueued = nextQueue[nextQueue.length - 1];
|
||||
const newName = newQueued.name;
|
||||
|
||||
if (newName !== this.state.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ name: '' });
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { action, name } = this.state;
|
||||
const { fee, pending, queue } = this.props;
|
||||
@ -120,7 +136,7 @@ export default class Names extends Component {
|
||||
label={ action === 'reserve' ? 'Reserve' : 'Drop' }
|
||||
primary
|
||||
icon={ <CheckIcon /> }
|
||||
onClick={ this.onSubmitClick }
|
||||
onTouchTap={ this.onSubmitClick }
|
||||
/>
|
||||
{ queue.length > 0
|
||||
? (<div>{ useSignerText }{ renderQueue(queue) }</div>)
|
||||
|
@ -52,7 +52,7 @@ export default class Records extends Component {
|
||||
label='Save'
|
||||
primary
|
||||
icon={ <SaveIcon /> }
|
||||
onClick={ this.onSaveClick }
|
||||
onTouchTap={ this.onSaveClick }
|
||||
/>
|
||||
</CardText>
|
||||
</Card>
|
||||
|
@ -174,7 +174,7 @@ export default class LoadContract extends Component {
|
||||
const secondaryText = description || `Saved ${moment(timestamp).fromNow()}`;
|
||||
const remove = removable
|
||||
? (
|
||||
<IconButton onClick={ onDelete }>
|
||||
<IconButton onTouchTap={ onDelete }>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
)
|
||||
|
@ -25,7 +25,7 @@ import ErrorIcon from 'material-ui/svg-icons/navigation/close';
|
||||
import { fromWei } from '../../../api/util/wei';
|
||||
import { Form, Input } from '../../../ui';
|
||||
|
||||
import terms from '../terms-of-service';
|
||||
import { termsOfService } from '../../../3rdparty/sms-verification';
|
||||
import styles from './gatherData.css';
|
||||
|
||||
export default class GatherData extends Component {
|
||||
@ -66,7 +66,7 @@ export default class GatherData extends Component {
|
||||
disabled={ isVerified }
|
||||
onCheck={ this.consentOnChange }
|
||||
/>
|
||||
<div className={ styles.terms }>{ terms }</div>
|
||||
<div className={ styles.terms }>{ termsOfService }</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
@ -123,8 +123,7 @@ export default class GatherData extends Component {
|
||||
<p className={ styles.message }>You already requested verification.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (hasRequested === false) {
|
||||
} else if (hasRequested === false) {
|
||||
return (
|
||||
<div className={ styles.container }>
|
||||
<SuccessIcon />
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
|
||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
||||
import DoneIcon from 'material-ui/svg-icons/action/done-all';
|
||||
import CancelIcon from 'material-ui/svg-icons/content/clear';
|
||||
|
||||
import { Button, IdentityIcon, Modal } from '../../ui';
|
||||
|
||||
@ -77,7 +77,7 @@ export default class SMSVerification extends Component {
|
||||
const cancel = (
|
||||
<Button
|
||||
key='cancel' label='Cancel'
|
||||
icon={ <ContentClear /> }
|
||||
icon={ <CancelIcon /> }
|
||||
onClick={ onClose }
|
||||
/>
|
||||
);
|
||||
@ -92,7 +92,7 @@ export default class SMSVerification extends Component {
|
||||
<Button
|
||||
key='done' label='Done'
|
||||
disabled={ !isStepValid }
|
||||
icon={ <ActionDoneAll /> }
|
||||
icon={ <DoneIcon /> }
|
||||
onClick={ onClose }
|
||||
/>
|
||||
</div>
|
||||
@ -140,24 +140,13 @@ export default class SMSVerification extends Component {
|
||||
setNumber, setConsentGiven, setCode
|
||||
} = this.props.store;
|
||||
|
||||
if (phase === 5) {
|
||||
return (<Done />);
|
||||
}
|
||||
if (phase === 4) {
|
||||
return (<SendConfirmation step={ step } tx={ confirmationTx } />);
|
||||
}
|
||||
if (phase === 3) {
|
||||
switch (phase) {
|
||||
case 0:
|
||||
return (
|
||||
<QueryCode
|
||||
number={ number } fee={ fee } isCodeValid={ isCodeValid }
|
||||
setCode={ setCode }
|
||||
/>
|
||||
<p>Loading SMS Verification.</p>
|
||||
);
|
||||
}
|
||||
if (phase === 2) {
|
||||
return (<SendRequest step={ step } tx={ requestTx } />);
|
||||
}
|
||||
if (phase === 1) {
|
||||
|
||||
case 1:
|
||||
const { setNumber, setConsentGiven } = this.props.store;
|
||||
return (
|
||||
<GatherData
|
||||
@ -166,11 +155,32 @@ export default class SMSVerification extends Component {
|
||||
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (phase === 0) {
|
||||
return (<p>Preparing awesomeness!</p>);
|
||||
}
|
||||
|
||||
case 2:
|
||||
return (
|
||||
<SendRequest step={ step } tx={ requestTx } />
|
||||
);
|
||||
|
||||
case 3:
|
||||
return (
|
||||
<QueryCode
|
||||
number={ number } fee={ fee } isCodeValid={ isCodeValid }
|
||||
setCode={ setCode }
|
||||
/>
|
||||
);
|
||||
|
||||
case 4:
|
||||
return (
|
||||
<SendConfirmation step={ step } tx={ confirmationTx } />
|
||||
);
|
||||
|
||||
case 5:
|
||||
return (
|
||||
<Done />
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ import { sha3 } from '../../api/util/sha3';
|
||||
|
||||
import Contracts from '../../contracts';
|
||||
|
||||
import { checkIfVerified, checkIfRequested, postToServer } from '../../contracts/sms-verification';
|
||||
import { checkIfVerified, checkIfRequested } from '../../contracts/sms-verification';
|
||||
import { postToServer } from '../../3rdparty/sms-verification';
|
||||
import checkIfTxFailed from '../../util/check-if-tx-failed';
|
||||
import waitForConfirmations from '../../util/wait-for-block-confirmations';
|
||||
|
||||
@ -87,7 +88,7 @@ export default class VerificationStore {
|
||||
this.account = account;
|
||||
|
||||
this.step = LOADING;
|
||||
Contracts.create(api).registry.getContract('smsVerification')
|
||||
Contracts.create(api).registry.getContract('smsverification')
|
||||
.then((contract) => {
|
||||
this.contract = contract;
|
||||
this.load();
|
||||
|
@ -155,24 +155,20 @@ export default class Status {
|
||||
|
||||
const { refreshStatus } = this._store.getState().nodeStatus;
|
||||
|
||||
const statusPromises = [ this._api.eth.syncing() ];
|
||||
const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ];
|
||||
|
||||
if (refreshStatus) {
|
||||
statusPromises.push(this._api.eth.hashrate());
|
||||
statusPromises.push(this._api.parity.netPeers());
|
||||
}
|
||||
|
||||
Promise
|
||||
.all(statusPromises)
|
||||
.then((statusResults) => {
|
||||
const status = statusResults.length === 1
|
||||
? {
|
||||
syncing: statusResults[0]
|
||||
}
|
||||
.then(([ syncing, netPeers, ...statusResults ]) => {
|
||||
const status = statusResults.length === 0
|
||||
? { syncing, netPeers }
|
||||
: {
|
||||
syncing: statusResults[0],
|
||||
hashrate: statusResults[1],
|
||||
netPeers: statusResults[2]
|
||||
syncing, netPeers,
|
||||
hashrate: statusResults[0]
|
||||
};
|
||||
|
||||
if (!isEqual(status, this._status)) {
|
||||
@ -251,7 +247,7 @@ export default class Status {
|
||||
.then(([
|
||||
clientVersion, defaultExtraData, netChain, netPort, rpcSettings, enode
|
||||
]) => {
|
||||
const isTest = netChain === 'morden' || netChain === 'testnet';
|
||||
const isTest = netChain === 'morden' || netChain === 'ropsten' || netChain === 'testnet';
|
||||
|
||||
const longStatus = {
|
||||
clientVersion,
|
||||
|
@ -31,7 +31,7 @@ const initialState = {
|
||||
gasLimit: new BigNumber(0),
|
||||
hashrate: new BigNumber(0),
|
||||
minGasPrice: new BigNumber(0),
|
||||
netChain: 'morden',
|
||||
netChain: 'ropsten',
|
||||
netPeers: {
|
||||
active: new BigNumber(0),
|
||||
connected: new BigNumber(0),
|
||||
|
@ -96,7 +96,7 @@ export default class TypedInput extends Component {
|
||||
<IconButton
|
||||
iconStyle={ iconStyle }
|
||||
style={ style }
|
||||
onClick={ this.onAddField }
|
||||
onTouchTap={ this.onAddField }
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
@ -104,7 +104,7 @@ export default class TypedInput extends Component {
|
||||
<IconButton
|
||||
iconStyle={ iconStyle }
|
||||
style={ style }
|
||||
onClick={ this.onRemoveField }
|
||||
onTouchTap={ this.onRemoveField }
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
|
@ -52,6 +52,7 @@
|
||||
"description": "Have a peak on internals of transaction queue of your node.",
|
||||
"author": "Parity Team <admin@ethcore.io>",
|
||||
"version": "1.0.0",
|
||||
"visible": true,
|
||||
"secure": true
|
||||
}
|
||||
]
|
||||
|
@ -67,7 +67,7 @@ export default class Dapps extends Component {
|
||||
label='edit'
|
||||
key='edit'
|
||||
icon={ <EyeIcon /> }
|
||||
onClick={ this.store.openModal }
|
||||
onTouchTap={ this.store.openModal }
|
||||
/>
|
||||
] }
|
||||
/>
|
||||
|
@ -25,7 +25,7 @@ export default class Account extends Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
address: PropTypes.string.isRequired,
|
||||
chain: PropTypes.string.isRequired,
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
balance: PropTypes.object // eth BigNumber, not required since it mght take time to fetch
|
||||
};
|
||||
|
||||
@ -51,11 +51,13 @@ export default class Account extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { address, chain, className } = this.props;
|
||||
const { address, isTest, className } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ `${styles.acc} ${className}` }>
|
||||
<AccountLink address={ address } chain={ chain }>
|
||||
<AccountLink
|
||||
address={ address }
|
||||
isTest={ isTest }>
|
||||
<IdentityIcon
|
||||
center
|
||||
address={ address } />
|
||||
@ -74,19 +76,23 @@ export default class Account extends Component {
|
||||
}
|
||||
|
||||
renderName () {
|
||||
const { address } = this.props;
|
||||
const { address, isTest } = this.props;
|
||||
const name = <IdentityName address={ address } empty />;
|
||||
|
||||
if (!name) {
|
||||
return (
|
||||
<AccountLink address={ address } chain={ this.props.chain }>
|
||||
<AccountLink
|
||||
address={ address }
|
||||
isTest={ isTest }>
|
||||
[{ this.shortAddress(address) }]
|
||||
</AccountLink>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AccountLink address={ address } chain={ this.props.chain } >
|
||||
<AccountLink
|
||||
address={ address }
|
||||
isTest={ isTest } >
|
||||
<span>
|
||||
<span className={ styles.name }>{ name }</span>
|
||||
<span className={ styles.address }>[{ this.tinyAddress(address) }]</span>
|
||||
|
@ -21,7 +21,7 @@ import styles from './AccountLink.css';
|
||||
|
||||
export default class AccountLink extends Component {
|
||||
static propTypes = {
|
||||
chain: PropTypes.string.isRequired,
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
address: PropTypes.string.isRequired,
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node
|
||||
@ -32,15 +32,15 @@ export default class AccountLink extends Component {
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
const { address, chain } = this.props;
|
||||
const { address, isTest } = this.props;
|
||||
|
||||
this.updateLink(address, chain);
|
||||
this.updateLink(address, isTest);
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const { address, chain } = nextProps;
|
||||
const { address, isTest } = nextProps;
|
||||
|
||||
this.updateLink(address, chain);
|
||||
this.updateLink(address, isTest);
|
||||
}
|
||||
|
||||
render () {
|
||||
@ -56,8 +56,8 @@ export default class AccountLink extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
updateLink (address, chain) {
|
||||
const link = addressLink(address, chain === 'morden' || chain === 'testnet');
|
||||
updateLink (address, isTest) {
|
||||
const link = addressLink(address, isTest);
|
||||
|
||||
this.setState({
|
||||
link
|
||||
|
@ -31,14 +31,16 @@ export default class RequestFinishedWeb3 extends Component {
|
||||
msg: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
isTest: PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
render () {
|
||||
const { payload, id, result, msg, status, error, date, className } = this.props;
|
||||
const { payload, id, result, msg, status, error, date, className, isTest } = this.props;
|
||||
|
||||
if (payload.sign) {
|
||||
const { sign } = payload;
|
||||
|
||||
return (
|
||||
<SignRequest
|
||||
className={ className }
|
||||
@ -49,12 +51,14 @@ export default class RequestFinishedWeb3 extends Component {
|
||||
msg={ msg }
|
||||
status={ status }
|
||||
error={ error }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (payload.transaction) {
|
||||
const { transaction } = payload;
|
||||
|
||||
return (
|
||||
<TransactionFinished
|
||||
className={ className }
|
||||
@ -69,6 +73,7 @@ export default class RequestFinishedWeb3 extends Component {
|
||||
date={ date }
|
||||
status={ status }
|
||||
error={ error }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ export default class RequestPendingWeb3 extends Component {
|
||||
PropTypes.shape({ transaction: PropTypes.object.isRequired }),
|
||||
PropTypes.shape({ sign: PropTypes.object.isRequired })
|
||||
]).isRequired,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
isTest: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
onConfirm = data => {
|
||||
@ -41,10 +42,11 @@ export default class RequestPendingWeb3 extends Component {
|
||||
};
|
||||
|
||||
render () {
|
||||
const { payload, id, className, isSending, date, onReject } = this.props;
|
||||
const { payload, id, className, isSending, date, onReject, isTest } = this.props;
|
||||
|
||||
if (payload.sign) {
|
||||
const { sign } = payload;
|
||||
|
||||
return (
|
||||
<SignRequest
|
||||
className={ className }
|
||||
@ -55,12 +57,14 @@ export default class RequestPendingWeb3 extends Component {
|
||||
id={ id }
|
||||
address={ sign.address }
|
||||
hash={ sign.hash }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (payload.transaction) {
|
||||
const { transaction } = payload;
|
||||
|
||||
return (
|
||||
<TransactionPending
|
||||
className={ className }
|
||||
@ -75,6 +79,7 @@ export default class RequestPendingWeb3 extends Component {
|
||||
to={ transaction.to }
|
||||
value={ transaction.value }
|
||||
date={ date }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -39,24 +39,15 @@ export default class SignRequest extends Component {
|
||||
onReject: PropTypes.func,
|
||||
status: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
chain: nullable(PropTypes.object),
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
balance: nullable(PropTypes.object)
|
||||
};
|
||||
|
||||
state = {
|
||||
chain: null,
|
||||
balance: null
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('could not fetch chain', err);
|
||||
});
|
||||
|
||||
this.context.api.eth.getBalance(this.props.address)
|
||||
.then((balance) => {
|
||||
this.setState({ balance });
|
||||
@ -68,6 +59,7 @@ export default class SignRequest extends Component {
|
||||
|
||||
render () {
|
||||
const { className } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ `${styles.container} ${className || ''}` }>
|
||||
{ this.renderDetails() }
|
||||
@ -77,15 +69,20 @@ export default class SignRequest extends Component {
|
||||
}
|
||||
|
||||
renderDetails () {
|
||||
const { address, hash } = this.props;
|
||||
const { balance, chain } = this.state;
|
||||
const { address, hash, isTest } = this.props;
|
||||
const { balance } = this.state;
|
||||
|
||||
if (!balance || !chain) return (<div />);
|
||||
if (!balance) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.signDetails }>
|
||||
<div className={ styles.address }>
|
||||
<Account address={ address } balance={ balance } chain={ chain } />
|
||||
<Account
|
||||
address={ address }
|
||||
balance={ balance }
|
||||
isTest={ isTest } />
|
||||
</div>
|
||||
<div className={ styles.info } title={ hash }>
|
||||
<p>Dapp is requesting to sign arbitrary transaction using this account.</p>
|
||||
@ -100,15 +97,17 @@ export default class SignRequest extends Component {
|
||||
|
||||
if (isFinished) {
|
||||
if (status === 'confirmed') {
|
||||
const { hash } = this.props;
|
||||
const { chain } = this.state;
|
||||
const { hash, isTest } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.actions }>
|
||||
<span className={ styles.isConfirmed }>Confirmed</span>
|
||||
<div>
|
||||
Transaction hash:
|
||||
<TxHashLink chain={ chain } txHash={ hash } className={ styles.txHash } />
|
||||
<TxHashLink
|
||||
isTest={ isTest }
|
||||
txHash={ hash }
|
||||
className={ styles.txHash } />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -47,13 +47,12 @@ export default class TransactionFinished extends Component {
|
||||
txHash: PropTypes.string, // undefined if transacation is rejected
|
||||
className: PropTypes.string,
|
||||
data: PropTypes.string,
|
||||
chain: nullable(PropTypes.object),
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
fromBalance: nullable(PropTypes.object),
|
||||
toBalance: nullable(PropTypes.object)
|
||||
};
|
||||
|
||||
state = {
|
||||
chain: null,
|
||||
fromBalance: null,
|
||||
toBalance: null
|
||||
};
|
||||
@ -64,14 +63,6 @@ export default class TransactionFinished extends Component {
|
||||
const totalValue = tUtil.getTotalValue(fee, value);
|
||||
this.setState({ totalValue });
|
||||
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('could not fetch chain', err);
|
||||
});
|
||||
|
||||
this.fetchBalance(from, 'fromBalance');
|
||||
if (to) {
|
||||
this.fetchBalance(to, 'toBalance');
|
||||
@ -79,8 +70,9 @@ export default class TransactionFinished extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { chain, fromBalance, toBalance } = this.state;
|
||||
if (!chain || !fromBalance || !toBalance) {
|
||||
const { fromBalance, toBalance } = this.state;
|
||||
|
||||
if (!fromBalance || !toBalance) {
|
||||
return (
|
||||
<div className={ `${styles.container} ${className}` }>
|
||||
<CircularProgress size={ 60 } />
|
||||
@ -130,16 +122,19 @@ export default class TransactionFinished extends Component {
|
||||
}
|
||||
|
||||
renderTxHash () {
|
||||
const { txHash } = this.props;
|
||||
const { chain } = this.state;
|
||||
if (!txHash || !chain) {
|
||||
const { txHash, isTest } = this.props;
|
||||
|
||||
if (!txHash) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
Transaction hash:
|
||||
<TxHashLink chain={ chain } txHash={ txHash } className={ styles.txHash } />
|
||||
<TxHashLink
|
||||
isTest={ isTest }
|
||||
txHash={ txHash }
|
||||
className={ styles.txHash } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ export default class TransactionMainDetails extends Component {
|
||||
fromBalance: PropTypes.object, // eth BigNumber, not required since it might take time to fetch
|
||||
value: PropTypes.object.isRequired, // wei hex
|
||||
totalValue: PropTypes.object.isRequired, // wei BigNumber
|
||||
chain: PropTypes.string.isRequired,
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
to: PropTypes.string, // undefined if it's a contract
|
||||
toBalance: PropTypes.object, // eth BigNumber - undefined if it's a contract or until it's fetched
|
||||
className: PropTypes.string,
|
||||
@ -39,11 +39,13 @@ export default class TransactionMainDetails extends Component {
|
||||
|
||||
componentWillMount () {
|
||||
const { value, totalValue } = this.props;
|
||||
|
||||
this.updateDisplayValues(value, totalValue);
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const { value, totalValue } = nextProps;
|
||||
|
||||
this.updateDisplayValues(value, totalValue);
|
||||
}
|
||||
|
||||
@ -59,6 +61,7 @@ export default class TransactionMainDetails extends Component {
|
||||
|
||||
render () {
|
||||
const { className, children } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ className }>
|
||||
{ this.renderTransfer() }
|
||||
@ -69,7 +72,8 @@ export default class TransactionMainDetails extends Component {
|
||||
}
|
||||
|
||||
renderTransfer () {
|
||||
const { from, fromBalance, to, toBalance, chain } = this.props;
|
||||
const { from, fromBalance, to, toBalance, isTest } = this.props;
|
||||
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
@ -78,7 +82,10 @@ export default class TransactionMainDetails extends Component {
|
||||
<div className={ styles.transaction }>
|
||||
<div className={ styles.from }>
|
||||
<div className={ styles.account }>
|
||||
<Account address={ from } balance={ fromBalance } chain={ chain } />
|
||||
<Account
|
||||
address={ from }
|
||||
balance={ fromBalance }
|
||||
isTest={ isTest } />
|
||||
</div>
|
||||
</div>
|
||||
<div className={ styles.tx }>
|
||||
@ -88,7 +95,10 @@ export default class TransactionMainDetails extends Component {
|
||||
</div>
|
||||
<div className={ styles.to }>
|
||||
<div className={ styles.account }>
|
||||
<Account address={ to } balance={ toBalance } chain={ chain } />
|
||||
<Account
|
||||
address={ to }
|
||||
balance={ toBalance }
|
||||
isTest={ isTest } />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -96,15 +106,20 @@ export default class TransactionMainDetails extends Component {
|
||||
}
|
||||
|
||||
renderContract () {
|
||||
const { from, fromBalance, to, chain } = this.props;
|
||||
const { from, fromBalance, to, isTest } = this.props;
|
||||
|
||||
if (to) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.transaction }>
|
||||
<div className={ styles.from }>
|
||||
<div className={ styles.account }>
|
||||
<Account address={ from } balance={ fromBalance } chain={ chain } />
|
||||
<Account
|
||||
address={ from }
|
||||
balance={ fromBalance }
|
||||
isTest={ isTest } />
|
||||
</div>
|
||||
</div>
|
||||
<div className={ styles.tx }>
|
||||
@ -126,6 +141,7 @@ export default class TransactionMainDetails extends Component {
|
||||
renderValue () {
|
||||
const { id } = this.props;
|
||||
const { valueDisplay, valueDisplayWei } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
@ -147,6 +163,7 @@ export default class TransactionMainDetails extends Component {
|
||||
renderTotalValue () {
|
||||
const { id } = this.props;
|
||||
const { totalValueDisplay, totalValueDisplayWei, feeEth } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
@ -164,5 +181,4 @@ export default class TransactionMainDetails extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import CircularProgress from 'material-ui/CircularProgress';
|
||||
import TransactionMainDetails from '../TransactionMainDetails';
|
||||
import TransactionPendingForm from '../TransactionPendingForm';
|
||||
import TransactionSecondaryDetails from '../TransactionSecondaryDetails';
|
||||
@ -43,7 +42,8 @@ export default class TransactionPending extends Component {
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
onReject: PropTypes.func.isRequired,
|
||||
isSending: PropTypes.bool.isRequired,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
isTest: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@ -51,7 +51,6 @@ export default class TransactionPending extends Component {
|
||||
};
|
||||
|
||||
state = {
|
||||
chain: null,
|
||||
fromBalance: null,
|
||||
toBalance: null
|
||||
};
|
||||
@ -64,28 +63,12 @@ export default class TransactionPending extends Component {
|
||||
const gasToDisplay = tUtil.getGasDisplay(gas);
|
||||
this.setState({ gasPriceEthmDisplay, totalValue, gasToDisplay });
|
||||
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('could not fetch chain', err);
|
||||
});
|
||||
|
||||
const { from, to } = this.props;
|
||||
this.fetchBalance(from, 'fromBalance');
|
||||
if (to) this.fetchBalance(to, 'toBalance');
|
||||
}
|
||||
|
||||
render () {
|
||||
if (!this.state.chain) {
|
||||
return (
|
||||
<div className={ `${styles.container} ${className}` }>
|
||||
<CircularProgress size={ 60 } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { totalValue, gasPriceEthmDisplay, gasToDisplay } = this.state;
|
||||
const { className, id, date, data, from } = this.props;
|
||||
|
||||
|
@ -74,7 +74,7 @@ class TransactionPendingFormConfirm extends Component {
|
||||
data-effect='solid'
|
||||
>
|
||||
<RaisedButton
|
||||
onClick={ this.onConfirm }
|
||||
onTouchTap={ this.onConfirm }
|
||||
className={ styles.confirmButton }
|
||||
fullWidth
|
||||
primary
|
||||
|
@ -37,7 +37,7 @@ export default class TransactionPendingFormReject extends Component {
|
||||
<strong>This cannot be undone</strong>
|
||||
</div>
|
||||
<RaisedButton
|
||||
onClick={ onReject }
|
||||
onTouchTap={ onReject }
|
||||
className={ styles.rejectButton }
|
||||
fullWidth
|
||||
label={ 'Reject Transaction' }
|
||||
|
@ -59,10 +59,13 @@ export default class TransactionSecondaryDetails extends Component {
|
||||
}
|
||||
|
||||
renderGasPrice () {
|
||||
if (!this.props.gasPriceEthmDisplay && !this.props.gasToDisplay) return null;
|
||||
if (!this.props.gasPriceEthmDisplay && !this.props.gasToDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { id } = this.props;
|
||||
const { gasPriceEthmDisplay, gasToDisplay } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
data-tip
|
||||
@ -83,11 +86,14 @@ export default class TransactionSecondaryDetails extends Component {
|
||||
}
|
||||
|
||||
renderData () {
|
||||
if (!this.props.data) return null;
|
||||
if (!this.props.data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { data, id } = this.props;
|
||||
let dataToDisplay = this.noData() ? 'no data' : tUtil.getShortData(data);
|
||||
const noDataClass = this.noData() ? styles.noData : '';
|
||||
|
||||
return (
|
||||
<div
|
||||
className={ `${styles.data} ${noDataClass}` }
|
||||
|
@ -22,17 +22,17 @@ export default class TxHashLink extends Component {
|
||||
|
||||
static propTypes = {
|
||||
txHash: PropTypes.string.isRequired,
|
||||
chain: PropTypes.string.isRequired,
|
||||
isTest: PropTypes.bool.isRequired,
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, txHash, className, chain } = this.props;
|
||||
const { children, txHash, className, isTest } = this.props;
|
||||
|
||||
return (
|
||||
<a
|
||||
href={ txLink(txHash, chain === 'morden' || chain === 'testnet') }
|
||||
href={ txLink(txHash, isTest) }
|
||||
target='_blank'
|
||||
className={ className }>
|
||||
{ children || txHash }
|
||||
|
@ -35,7 +35,8 @@ class Embedded extends Component {
|
||||
actions: PropTypes.shape({
|
||||
startConfirmRequest: PropTypes.func.isRequired,
|
||||
startRejectRequest: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
}).isRequired,
|
||||
isTest: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
render () {
|
||||
@ -70,7 +71,7 @@ class Embedded extends Component {
|
||||
}
|
||||
|
||||
renderPending = (data) => {
|
||||
const { actions } = this.props;
|
||||
const { actions, isTest } = this.props;
|
||||
const { payload, id, isSending, date } = data;
|
||||
|
||||
return (
|
||||
@ -83,6 +84,7 @@ class Embedded extends Component {
|
||||
id={ id }
|
||||
payload={ payload }
|
||||
date={ date }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -93,11 +95,13 @@ class Embedded extends Component {
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { isTest } = state.nodeStatus;
|
||||
const { actions, signer } = state;
|
||||
|
||||
return {
|
||||
actions,
|
||||
signer
|
||||
signer,
|
||||
isTest
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ class RequestsPage extends Component {
|
||||
actions: PropTypes.shape({
|
||||
startConfirmRequest: PropTypes.func.isRequired,
|
||||
startRejectRequest: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
}).isRequired,
|
||||
isTest: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
render () {
|
||||
@ -96,7 +97,7 @@ class RequestsPage extends Component {
|
||||
}
|
||||
|
||||
renderPending = (data) => {
|
||||
const { actions } = this.props;
|
||||
const { actions, isTest } = this.props;
|
||||
const { payload, id, isSending, date } = data;
|
||||
|
||||
return (
|
||||
@ -109,11 +110,13 @@ class RequestsPage extends Component {
|
||||
id={ id }
|
||||
payload={ payload }
|
||||
date={ date }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderFinished = (data) => {
|
||||
const { isTest } = this.props;
|
||||
const { payload, id, result, msg, status, error, date } = data;
|
||||
|
||||
return (
|
||||
@ -127,6 +130,7 @@ class RequestsPage extends Component {
|
||||
error={ error }
|
||||
payload={ payload }
|
||||
date={ date }
|
||||
isTest={ isTest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -143,7 +147,14 @@ class RequestsPage extends Component {
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return state;
|
||||
const { isTest } = state.nodeStatus;
|
||||
const { actions, signer } = state;
|
||||
|
||||
return {
|
||||
actions,
|
||||
signer,
|
||||
isTest
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
|
@ -57,7 +57,7 @@ export default class CallsToolbar extends Component {
|
||||
<div className={ styles.callActions } { ...this._test('button-container') }>
|
||||
<IconButton
|
||||
className={ styles.callAction }
|
||||
onClick={ this.setCall }
|
||||
onTouchTap={ this.setCall }
|
||||
tooltip='Set'
|
||||
tooltipPosition='top-left'
|
||||
{ ...this._test('button-setCall') }
|
||||
@ -66,7 +66,7 @@ export default class CallsToolbar extends Component {
|
||||
</IconButton>
|
||||
<IconButton
|
||||
className={ styles.callAction }
|
||||
onClick={ this.makeCall }
|
||||
onTouchTap={ this.makeCall }
|
||||
tooltip='Fire again'
|
||||
tooltipPosition='top-left'
|
||||
{ ...this._test('button-makeCall') }
|
||||
|
@ -45,7 +45,7 @@ export default class ScrollTopButton extends Component {
|
||||
return (
|
||||
<IconButton
|
||||
className={ `${styles.scrollButton} ${hiddenClass}` }
|
||||
onClick={ this._scrollToTop }>
|
||||
onTouchTap={ this._scrollToTop }>
|
||||
<ArrowUpwardIcon />
|
||||
</IconButton>
|
||||
);
|
||||
|
@ -37,6 +37,7 @@ module.exports = {
|
||||
entry: {
|
||||
// dapps
|
||||
'basiccoin': ['./dapps/basiccoin.js'],
|
||||
'dappreg': ['./dapps/dappreg.js'],
|
||||
'githubhint': ['./dapps/githubhint.js'],
|
||||
'registry': ['./dapps/registry.js'],
|
||||
'signaturereg': ['./dapps/signaturereg.js'],
|
||||
|
@ -102,7 +102,7 @@ fn import(i: ImportAccounts) -> Result<String, String> {
|
||||
let from = DiskDirectory::at(path);
|
||||
imported += try!(import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")).len();
|
||||
}
|
||||
Ok(format!("{}", imported))
|
||||
Ok(format!("{} account(s) imported", imported))
|
||||
}
|
||||
|
||||
fn import_geth(i: ImportFromGethAccounts) -> Result<String, String> {
|
||||
|
@ -32,7 +32,7 @@ Operating Options:
|
||||
(default: {flag_mode_alarm}).
|
||||
--chain CHAIN Specify the blockchain type. CHAIN may be either a
|
||||
JSON chain specification file or olympic, frontier,
|
||||
homestead, mainnet, morden, classic, expanse,
|
||||
homestead, mainnet, morden, ropsten, classic, expanse,
|
||||
testnet or dev (default: {flag_chain}).
|
||||
-d --db-path PATH Specify the database & configuration directory path
|
||||
(default: {flag_db_path}).
|
||||
|
@ -313,7 +313,7 @@ impl Configuration {
|
||||
|
||||
fn chain(&self) -> String {
|
||||
if self.args.flag_testnet {
|
||||
"morden".to_owned()
|
||||
"ropsten".to_owned()
|
||||
} else {
|
||||
self.args.flag_chain.clone()
|
||||
}
|
||||
@ -905,7 +905,7 @@ mod tests {
|
||||
// then
|
||||
assert_eq!(conf.network_settings(), NetworkSettings {
|
||||
name: "testname".to_owned(),
|
||||
chain: "morden".to_owned(),
|
||||
chain: "ropsten".to_owned(),
|
||||
network_port: 30303,
|
||||
rpc_enabled: true,
|
||||
rpc_interface: "local".to_owned(),
|
||||
|
@ -110,7 +110,7 @@ mod server {
|
||||
|
||||
use rpc_apis;
|
||||
use ethcore_rpc::is_major_importing;
|
||||
use ethcore_dapps::ContractClient;
|
||||
use hash_fetch::urlhint::ContractClient;
|
||||
|
||||
pub use ethcore_dapps::Server as WebappServer;
|
||||
|
||||
|
@ -42,6 +42,7 @@ extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate rlp;
|
||||
extern crate ethcore_hash_fetch as hash_fetch;
|
||||
|
||||
extern crate json_ipc_server as jsonipc;
|
||||
|
||||
|
@ -28,6 +28,7 @@ use user_defaults::UserDefaults;
|
||||
pub enum SpecType {
|
||||
Mainnet,
|
||||
Testnet,
|
||||
Ropsten,
|
||||
Olympic,
|
||||
Classic,
|
||||
Expanse,
|
||||
@ -49,6 +50,7 @@ impl str::FromStr for SpecType {
|
||||
"frontier" | "homestead" | "mainnet" => SpecType::Mainnet,
|
||||
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
|
||||
"morden" | "testnet" => SpecType::Testnet,
|
||||
"ropsten" => SpecType::Ropsten,
|
||||
"olympic" => SpecType::Olympic,
|
||||
"expanse" => SpecType::Expanse,
|
||||
"dev" => SpecType::Dev,
|
||||
@ -63,6 +65,7 @@ impl SpecType {
|
||||
match *self {
|
||||
SpecType::Mainnet => Ok(ethereum::new_frontier()),
|
||||
SpecType::Testnet => Ok(ethereum::new_morden()),
|
||||
SpecType::Ropsten => Ok(ethereum::new_ropsten()),
|
||||
SpecType::Olympic => Ok(ethereum::new_olympic()),
|
||||
SpecType::Classic => Ok(ethereum::new_classic()),
|
||||
SpecType::Expanse => Ok(ethereum::new_expanse()),
|
||||
@ -285,6 +288,7 @@ mod tests {
|
||||
assert_eq!(SpecType::Mainnet, "mainnet".parse().unwrap());
|
||||
assert_eq!(SpecType::Testnet, "testnet".parse().unwrap());
|
||||
assert_eq!(SpecType::Testnet, "morden".parse().unwrap());
|
||||
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
|
||||
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
|
||||
}
|
||||
|
||||
|
@ -683,6 +683,7 @@ macro_rules! construct_uint {
|
||||
bytes[i] = (arr[pos] >> ((rev % 8) * 8)) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exp10(n: usize) -> Self {
|
||||
match n {
|
||||
|
Loading…
Reference in New Issue
Block a user