diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 286fe0d4e..353941ae0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -254,7 +254,7 @@ linux-armv7: - cat .cargo/config - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity - - export SHA3=$(rhash --sha3-256 ~/Core/parity/target/release/parity -p %h) + - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - md5sum target/$PLATFORM/release/parity > parity.md5 - sh scripts/deb-build.sh armhf - cp target/$PLATFORM/release/parity deb/usr/bin/parity @@ -300,7 +300,7 @@ linux-arm: - cat .cargo/config - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity - - export SHA3=$(rhash --sha3-256 ~/Core/parity/target/release/parity -p %h) + - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - md5sum target/$PLATFORM/release/parity > parity.md5 - sh scripts/deb-build.sh armhf - cp target/$PLATFORM/release/parity deb/usr/bin/parity @@ -346,7 +346,7 @@ linux-armv6: - cat .cargo/config - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - arm-linux-gnueabi-strip target/$PLATFORM/release/parity - - export SHA3=$(rhash --sha3-256 ~/Core/parity/target/release/parity -p %h) + - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - md5sum target/$PLATFORM/release/parity > parity.md5 - aws configure set aws_access_key_id $s3_key - aws configure set aws_secret_access_key $s3_secret @@ -385,7 +385,7 @@ linux-aarch64: - cat .cargo/config - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - aarch64-linux-gnu-strip target/$PLATFORM/release/parity - - export SHA3=$(rhash --sha3-256 ~/Core/parity/target/release/parity -p %h) + - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - md5sum target/$PLATFORM/release/parity > parity.md5 - sh scripts/deb-build.sh arm64 - cp target/$PLATFORM/release/parity deb/usr/bin/parity @@ -522,10 +522,10 @@ docker-build: script: - if [ "$CI_BUILD_REF_NAME" == "beta-release" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi - docker login -u $Docker_Hub_User -p $Docker_Hub_Pass - - sh scripts/docker-build.sh $DOCKER_TAG + - sh scripts/docker-build.sh $DOCKER_TAG ethcore - docker logout - docker login -u $Docker_Hub_User_Parity -p $Docker_Hub_Pass_Parity - - sh scripts/docker-build.sh $DOCKER_TAG + - sh scripts/docker-build.sh $DOCKER_TAG parity - docker logout tags: - docker diff --git a/Cargo.lock b/Cargo.lock index 9d4d7a458..9b9710967 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1705,6 +1705,7 @@ dependencies = [ "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1712,6 +1713,7 @@ dependencies = [ "parity-reactor 0.1.0", "parity-updater 1.7.0", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1721,6 +1723,7 @@ dependencies = [ "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1778,7 +1781,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#15530d00f0a48462e764a909e15a0c74870b1fad" +source = "git+https://github.com/paritytech/js-precompiled.git#0826776d9190ee6945bfe481e10b19ec05b3a049" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2553,6 +2556,15 @@ dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-timer" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-uds" version = "0.1.4" @@ -2986,6 +2998,7 @@ dependencies = [ "checksum tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)" = "" "checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" +"checksum tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86f33def658c14724fc13ec6289b3875a8152ee8ae767a5b1ccbded363b03db8" "checksum tokio-uds 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd209039933255ea77c6d7a1d18abc20b997d161acb900acca6eb74cdd049f31" "checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6" "checksum toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442dfc13508e603c3f763274361db7f79d7469a0e95c411cde53662ab30fc72" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index b80d68317..a1f47251c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -377,7 +377,7 @@ impl Client { let chain = self.chain.read(); // Check the block isn't so old we won't be able to enact it. let best_block_number = chain.best_block_number(); - if best_block_number >= self.history && header.number() <= best_block_number - self.history { + if self.pruning_info().earliest_state > header.number() { warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); return Err(()); } @@ -770,7 +770,7 @@ impl Client { let db = self.state_db.lock().boxed_clone(); // early exit for pruned blocks - if db.is_pruned() && self.chain.read().best_block_number() >= block_number + self.history { + if db.is_pruned() && self.pruning_info().earliest_state > block_number { return None; } @@ -871,7 +871,7 @@ impl Client { let best_block_number = self.chain_info().best_block_number; let block_number = self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at))?; - if best_block_number > self.history + block_number && db.is_pruned() { + if db.is_pruned() && self.pruning_info().earliest_state > block_number { return Err(snapshot::Error::OldBlockPrunedDB.into()); } @@ -1354,8 +1354,7 @@ impl BlockChainClient for Client { .collect(); match (transaction, previous_receipts) { (Some(transaction), Some(previous_receipts)) => { - let schedule = self.engine().schedule(block_number); - Some(transaction_receipt(&schedule, transaction, previous_receipts)) + Some(transaction_receipt(self.engine(), transaction, previous_receipts)) }, _ => None, } @@ -1748,7 +1747,7 @@ impl Drop for Client { /// Returns `LocalizedReceipt` given `LocalizedTransaction` /// and a vector of receipts from given block up to transaction index. -fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { +fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); let sender = tx.sender(); @@ -1772,7 +1771,7 @@ fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut re gas_used: receipt.gas_used - prior_gas_used, contract_address: match tx.action { Action::Call(_) => None, - Action::Create => Some(contract_address(schedule.create_address, &sender, &tx.nonce, &tx.data.sha3())) + Action::Create => Some(contract_address(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data.sha3())) }, logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { entry: log, @@ -1827,17 +1826,17 @@ mod tests { #[test] fn should_return_correct_log_index() { use super::transaction_receipt; - use evm::schedule::Schedule; use ethkey::KeyPair; use log_entry::{LogEntry, LocalizedLogEntry}; use receipt::{Receipt, LocalizedReceipt}; use transaction::{Transaction, LocalizedTransaction, Action}; use util::Hashable; + use tests::helpers::TestEngine; // given let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap(); let secret = key.secret(); - let schedule = Schedule::new_homestead(); + let engine = TestEngine::new(0); let block_number = 1; let block_hash = 5.into(); @@ -1881,7 +1880,7 @@ mod tests { }]; // when - let receipt = transaction_receipt(&schedule, transaction, receipts); + let receipt = transaction_receipt(&engine, transaction, receipts); // then assert_eq!(receipt, LocalizedReceipt { diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index ae57976b4..7041048b8 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -48,6 +48,7 @@ use receipt::Receipt; use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; +use evm::CreateContractAddress; use ethkey::Signature; use util::*; @@ -294,4 +295,9 @@ pub trait Engine : Sync + Send { fn snapshot_components(&self) -> Option> { None } + + /// Returns new contract address generation scheme at given block number. + fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress { + if number >= self.params().eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce } + } } diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index 41c9e1ea1..eef1a9e3b 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -278,7 +278,7 @@ lazy_static! { arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero); arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special); arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Special); - arr[CREATE_P2SH as usize] = InstructionInfo::new("CREATE_P2SH", 0, 3, 1, true, GasPriceTier::Special); + arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 0, 3, 1, true, GasPriceTier::Special); arr }; } @@ -555,7 +555,7 @@ pub const RETURN: Instruction = 0xf3; /// like CALLCODE but keeps caller's value and sender pub const DELEGATECALL: Instruction = 0xf4; /// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160 -pub const CREATE_P2SH: Instruction = 0xfb; +pub const CREATE2: Instruction = 0xfb; /// halt execution and register account for later deletion pub const SUICIDE: Instruction = 0xff; diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs index fb0c86d35..246c93bad 100644 --- a/ethcore/src/evm/interpreter/gasometer.rs +++ b/ethcore/src/evm/interpreter/gasometer.rs @@ -223,7 +223,7 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) }, - instructions::CREATE | instructions::CREATE_P2SH => { + instructions::CREATE | instructions::CREATE2 => { let gas = Gas::from(schedule.create_gas); let mem = mem_needed(stack.peek(1), stack.peek(2))?; diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 7fbab7ebc..f08737d24 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -183,7 +183,7 @@ impl Interpreter { let schedule = ext.schedule(); if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) || - (instruction == instructions::CREATE_P2SH && !schedule.have_create_p2sh) { + (instruction == instructions::CREATE2 && !schedule.have_create2) { return Err(evm::Error::BadInstruction { instruction: instruction @@ -268,12 +268,12 @@ impl Interpreter { instructions::JUMPDEST => { // ignore }, - instructions::CREATE | instructions::CREATE_P2SH => { + instructions::CREATE | instructions::CREATE2 => { let endowment = stack.pop_back(); let init_off = stack.pop_back(); let init_size = stack.pop_back(); - let address_scheme = if instruction == instructions::CREATE { ext.schedule().create_address } else { CreateContractAddress::FromSenderAndCodeHash }; + let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); let contract_code = self.mem.read_slice(init_off, init_size); diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index 97df4d784..3e01f3925 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . //! Cost schedule and other parameterisations for the EVM. -use evm::CreateContractAddress; /// Definition of the cost schedule and other parameterisations for the EVM. pub struct Schedule { @@ -24,7 +23,7 @@ pub struct Schedule { /// Does it have a delegate cal pub have_delegate_call: bool, /// Does it have a CREATE_P2SH instruction - pub have_create_p2sh: bool, + pub have_create2: bool, /// VM stack limit pub stack_limit: usize, /// Max number of nested calls/creates @@ -102,8 +101,6 @@ pub struct Schedule { pub no_empty: bool, /// Kill empty accounts if touched. pub kill_empty: bool, - /// Contract address generation scheme - pub create_address: CreateContractAddress, } impl Schedule { @@ -118,11 +115,11 @@ impl Schedule { } /// Schedule for the post-EIP-150-era of the Ethereum main net. - pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_create_p2sh: bool) -> Schedule { + pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_metropolis_instructions: bool) -> Schedule { Schedule { exceptional_failed_code_deposit: true, have_delegate_call: true, - have_create_p2sh: have_create_p2sh, + have_create2: have_metropolis_instructions, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -161,7 +158,6 @@ impl Schedule { sub_gas_cap_divisor: Some(64), no_empty: no_empty, kill_empty: kill_empty, - create_address: if have_create_p2sh { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }, } } @@ -174,7 +170,7 @@ impl Schedule { Schedule { exceptional_failed_code_deposit: efcd, have_delegate_call: hdc, - have_create_p2sh: false, + have_create2: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -213,7 +209,6 @@ impl Schedule { sub_gas_cap_divisor: None, no_empty: false, kill_empty: false, - create_address: CreateContractAddress::FromSenderAndNonce, } } } diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 494d59db9..1974a6c8d 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -185,7 +185,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let (gas_left, output) = match t.action { Action::Create => { let code_hash = t.data.sha3(); - let new_address = contract_address(schedule.create_address, &sender, &nonce, &code_hash); + let new_address = contract_address(self.engine.create_address_scheme(self.info.number), &sender, &nonce, &code_hash); let params = ActionParams { code_address: new_address.clone(), code_hash: code_hash, @@ -386,8 +386,8 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { vm_tracer: &mut V, ) -> evm::Result where T: Tracer, V: VMTracer { - let schedule = self.engine.schedule(self.info.number); - if schedule.create_address != CreateContractAddress::FromSenderAndNonce && self.state.exists(¶ms.address)? { + let scheme = self.engine.create_address_scheme(self.info.number); + if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? { return Err(evm::Error::OutOfGas); } @@ -398,6 +398,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let mut unconfirmed_substate = Substate::new(); // create contract and transfer value to it if necessary + let schedule = self.engine.schedule(self.info.number); let nonce_offset = if schedule.no_empty {1} else {0}.into(); let prev_bal = self.state.balance(¶ms.address)?; if let ActionValue::Transfer(val) = params.value { diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ed551e2f3..38e97f683 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1048,7 +1048,7 @@ impl MinerService for Miner { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); - Some(contract_address(self.engine.schedule(pending.header().number()).create_address, &sender, &tx.nonce, &tx.data.sha3())) + Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data.sha3())) } }, logs: receipt.logs.clone(), diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 639fac053..e710559df 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -238,7 +238,7 @@ pub fn check_proof( /// Reverting a checkpoint with `revert_to_checkpoint` involves copying /// original values from the latest checkpoint back into `cache`. The code /// takes care not to overwrite cached storage while doing that. -/// checkpoint can be discateded with `discard_checkpoint`. All of the orignal +/// checkpoint can be discarded with `discard_checkpoint`. All of the orignal /// backed-up values are moved into a parent checkpoint (if any). /// pub struct State { @@ -433,6 +433,11 @@ impl State { self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null())) } + /// Determine whether an account exists and has code. + pub fn exists_and_has_code(&self, a: &Address) -> trie::Result { + self.ensure_cached(a, RequireCache::CodeSize, false, |a| a.map_or(false, |a| a.code_size().map_or(false, |size| size != 0))) + } + /// Get the balance of account `a`. pub fn balance(&self, a: &Address) -> trie::Result { self.ensure_cached(a, RequireCache::None, true, diff --git a/ethcrypto/src/lib.rs b/ethcrypto/src/lib.rs index ea0ea9754..4f14cf4d9 100644 --- a/ethcrypto/src/lib.rs +++ b/ethcrypto/src/lib.rs @@ -34,6 +34,9 @@ pub const KEY_LENGTH: usize = 32; pub const KEY_ITERATIONS: usize = 10240; pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2; +/// Default MAC to use (in RPC). +pub const DEFAULT_MAC: [u8; 2] = [0, 0]; + #[derive(PartialEq, Debug)] pub enum ScryptError { // log(N) < r / 16 diff --git a/js/package.json b/js/package.json index 17a98eeb7..cd223942e 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.65", + "version": "1.7.69", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", @@ -148,7 +148,7 @@ "stylelint": "7.9.0", "stylelint-config-standard": "16.0.0", "to-source": "2.0.3", - "uglify-js": "2.8.16", + "uglify-js": "2.8.22", "url-loader": "0.5.7", "webpack": "2.2.1", "webpack-bundle-size-analyzer": "2.5.0", @@ -162,6 +162,7 @@ "@parity/abi": "file:src/abi", "@parity/api": "file:src/api", "@parity/jsonrpc": "file:src/jsonrpc", + "@parity/shared": "file:src/shared", "@parity/ui": "file:src/ui", "@parity/wordlist": "1.0.1", "base32.js": "0.1.0", diff --git a/js/src/abi/spec/event/event.js b/js/src/abi/spec/event/event.js index 071a73965..604f58cb1 100644 --- a/js/src/abi/spec/event/event.js +++ b/js/src/abi/spec/event/event.js @@ -99,15 +99,15 @@ export default class Event { const namedTokens = {}; topicParams.forEach((param, idx) => { - namedTokens[param.name] = topicTokens[idx]; + namedTokens[param.name || idx] = topicTokens[idx]; }); dataParams.forEach((param, idx) => { - namedTokens[param.name] = dataTokens[idx]; + namedTokens[param.name || idx] = dataTokens[idx]; }); const inputParamTypes = this.inputParamTypes(); const decodedParams = this.inputParamNames() - .map((name, idx) => new DecodedLogParam(name, inputParamTypes[idx], namedTokens[name])); + .map((name, idx) => new DecodedLogParam(name, inputParamTypes[idx], namedTokens[name || idx])); return new DecodedLog(decodedParams, address); } diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js index 77c9568a9..d6c71e3df 100644 --- a/js/src/api/contract/contract.js +++ b/js/src/api/contract/contract.js @@ -182,10 +182,11 @@ export default class Contract { log.params = {}; log.event = event.name; - decoded.params.forEach((param) => { + decoded.params.forEach((param, index) => { const { type, value } = param.token; + const key = param.name || index; - log.params[param.name] = { type, value }; + log.params[key] = { type, value }; }); return log; diff --git a/js/src/api/format/output.js b/js/src/api/format/output.js index ddb8b79f8..a712da5fe 100644 --- a/js/src/api/format/output.js +++ b/js/src/api/format/output.js @@ -93,6 +93,16 @@ export function outChainStatus (status) { } export function outDate (date) { + if (typeof date.toISOString === 'function') { + return date; + } + + try { + if (typeof date === 'string' && (new Date(date)).toISOString() === date) { + return new Date(date); + } + } catch (error) {} + return new Date(outNumber(date).toNumber() * 1000); } diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index 53610545a..674091563 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -70,11 +70,21 @@ export default class Parity { .execute('parity_checkRequest', inNumber16(requestId)); } + cidV0 (data) { + return this._transport + .execute('parity_cidV0', inData(data)); + } + closeVault (vaultName) { return this._transport .execute('parity_closeVault', vaultName); } + composeTransaction (options) { + return this._transport + .execute('parity_composeTransaction', inOptions(options)); + } + consensusCapability () { return this._transport .execute('parity_consensusCapability'); diff --git a/js/src/dapps/chaindeploy/_dapps.js b/js/src/dapps/chaindeploy/_dapps.js index e9eaa83a8..8f32bb5e1 100644 --- a/js/src/dapps/chaindeploy/_dapps.js +++ b/js/src/dapps/chaindeploy/_dapps.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtinsJson from '~/config/dappsBuiltin.json'; +import builtinsJson from '@parity/shared/config/dappsBuiltin.json'; const REGISTER_URLS = { console: 'https://raw.githubusercontent.com/paritytech/console/3ea0dbfefded359ccdbea37bc4cf350c0aa16948/console.jpeg', diff --git a/js/src/dapps/chaindeploy/contracts/badgereg.js b/js/src/dapps/chaindeploy/contracts/badgereg.js index ccd6b28c1..2a1dc4012 100644 --- a/js/src/dapps/chaindeploy/contracts/badgereg.js +++ b/js/src/dapps/chaindeploy/contracts/badgereg.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/badgereg'; +import abi from '@parity/shared/contracts/abi/badgereg'; + import { compiler, source as sourceUrl, output as byteCode } from './code/badgereg'; const id = 'badgereg'; diff --git a/js/src/dapps/chaindeploy/contracts/dappreg.js b/js/src/dapps/chaindeploy/contracts/dappreg.js index 71379bf8b..7fd705455 100644 --- a/js/src/dapps/chaindeploy/contracts/dappreg.js +++ b/js/src/dapps/chaindeploy/contracts/dappreg.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/dappreg'; +import abi from '@parity/shared/contracts/abi/dappreg'; + import { compiler, source as sourceUrl, output as byteCode } from './code/dappreg'; const id = 'dappreg'; // 7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03 diff --git a/js/src/dapps/chaindeploy/contracts/gavcoin.js b/js/src/dapps/chaindeploy/contracts/gavcoin.js index f7518ef53..ffbfe6e28 100644 --- a/js/src/dapps/chaindeploy/contracts/gavcoin.js +++ b/js/src/dapps/chaindeploy/contracts/gavcoin.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/gavcoin'; +import abi from '@parity/shared/contracts/abi/gavcoin'; + import { compiler, source as sourceUrl, output as byteCode } from './code/gavcoin'; const isExternal = true; diff --git a/js/src/dapps/chaindeploy/contracts/githubhint.js b/js/src/dapps/chaindeploy/contracts/githubhint.js index 5198e38b5..1c40834a5 100644 --- a/js/src/dapps/chaindeploy/contracts/githubhint.js +++ b/js/src/dapps/chaindeploy/contracts/githubhint.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/githubhint'; +import abi from '@parity/shared/contracts/abi/githubhint'; + import { compiler, source as sourceUrl, output as byteCode } from './code/githubhint'; const id = 'githubhint'; diff --git a/js/src/dapps/chaindeploy/contracts/registry.js b/js/src/dapps/chaindeploy/contracts/registry.js index 1b44f4245..4c2ea2ec0 100644 --- a/js/src/dapps/chaindeploy/contracts/registry.js +++ b/js/src/dapps/chaindeploy/contracts/registry.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/registry2'; +import abi from '@parity/shared/contracts/abi/registry2'; + import { compiler, source as sourceUrl, output as byteCode } from './code/registry'; const id = 'registry'; diff --git a/js/src/dapps/chaindeploy/contracts/signaturereg.js b/js/src/dapps/chaindeploy/contracts/signaturereg.js index 6d9f9bf60..cd35e14e8 100644 --- a/js/src/dapps/chaindeploy/contracts/signaturereg.js +++ b/js/src/dapps/chaindeploy/contracts/signaturereg.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/signaturereg'; +import abi from '@parity/shared/contracts/abi/signaturereg'; + import { compiler, source as sourceUrl, output as byteCode } from './code/signaturereg'; const id = 'signaturereg'; diff --git a/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js b/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js index d07435fdd..489614b6c 100644 --- a/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js +++ b/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/basiccoinmanager'; +import abi from '@parity/shared/contracts/abi/basiccoinmanager'; + import { compiler, source as sourceUrl, output as byteCode } from './code/tokendeploy'; const id = 'basiccoinmgr'; diff --git a/js/src/dapps/chaindeploy/contracts/tokenreg.js b/js/src/dapps/chaindeploy/contracts/tokenreg.js index 11ee29fa1..946977436 100644 --- a/js/src/dapps/chaindeploy/contracts/tokenreg.js +++ b/js/src/dapps/chaindeploy/contracts/tokenreg.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/tokenreg'; +import abi from '@parity/shared/contracts/abi/tokenreg'; + import { compiler, source as sourceUrl, output as byteCode } from './code/tokenreg'; const id = 'tokenreg'; diff --git a/js/src/dapps/chaindeploy/contracts/verifyEmail.js b/js/src/dapps/chaindeploy/contracts/verifyEmail.js index 0176d5949..300e58e4a 100644 --- a/js/src/dapps/chaindeploy/contracts/verifyEmail.js +++ b/js/src/dapps/chaindeploy/contracts/verifyEmail.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/email-verification'; +import abi from '@parity/shared/contracts/abi/email-verification'; + import { compiler, source as sourceUrl, output as byteCode } from './code/verifyEmail'; const isBadge = true; diff --git a/js/src/dapps/chaindeploy/contracts/verifySms.js b/js/src/dapps/chaindeploy/contracts/verifySms.js index d7ea50902..51eb248af 100644 --- a/js/src/dapps/chaindeploy/contracts/verifySms.js +++ b/js/src/dapps/chaindeploy/contracts/verifySms.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import abi from '~/contracts/abi/sms-verification'; +import abi from '@parity/shared/contracts/abi/sms-verification'; + import { compiler, source as sourceUrl, output as byteCode } from './code/verifySms'; const isBadge = true; diff --git a/js/src/dapps/chaindeploy/contracts/wallet.js b/js/src/dapps/chaindeploy/contracts/wallet.js index 6639cba80..e4b11059f 100644 --- a/js/src/dapps/chaindeploy/contracts/wallet.js +++ b/js/src/dapps/chaindeploy/contracts/wallet.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { walletCompiler as compiler, walletLibrary as byteCode, walletLibraryABI as abiJson, walletLibraryRegKey as id, walletSource as sourceUrl } from '~/contracts/code/wallet'; +import { walletCompiler as compiler, walletLibrary as byteCode, walletLibraryABI as abiJson, walletLibraryRegKey as id, walletSource as sourceUrl } from '@parity/shared/contracts/code/wallet'; const abi = JSON.parse(abiJson); const deployParams = []; diff --git a/js/src/dapps/chaindeploy/dapps/console.js b/js/src/dapps/chaindeploy/dapps/console.js index bc9cc7d43..dc87e1bc4 100644 --- a/js/src/dapps/chaindeploy/dapps/console.js +++ b/js/src/dapps/chaindeploy/dapps/console.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'console'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/dappreg.js b/js/src/dapps/chaindeploy/dapps/dappreg.js index c3939015a..fbf2589d7 100644 --- a/js/src/dapps/chaindeploy/dapps/dappreg.js +++ b/js/src/dapps/chaindeploy/dapps/dappreg.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'dappreg'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/githubhint.js b/js/src/dapps/chaindeploy/dapps/githubhint.js index 8a6b75d12..7fc16489a 100644 --- a/js/src/dapps/chaindeploy/dapps/githubhint.js +++ b/js/src/dapps/chaindeploy/dapps/githubhint.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'githubhint'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/localtx.js b/js/src/dapps/chaindeploy/dapps/localtx.js index 61f1f142d..8f3d9330b 100644 --- a/js/src/dapps/chaindeploy/dapps/localtx.js +++ b/js/src/dapps/chaindeploy/dapps/localtx.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'localtx'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/registry.js b/js/src/dapps/chaindeploy/dapps/registry.js index 5a28e3604..d5527aa59 100644 --- a/js/src/dapps/chaindeploy/dapps/registry.js +++ b/js/src/dapps/chaindeploy/dapps/registry.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'registry'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/signaturereg.js b/js/src/dapps/chaindeploy/dapps/signaturereg.js index acf939d72..c1e1f1063 100644 --- a/js/src/dapps/chaindeploy/dapps/signaturereg.js +++ b/js/src/dapps/chaindeploy/dapps/signaturereg.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'signaturereg'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/tokendeploy.js b/js/src/dapps/chaindeploy/dapps/tokendeploy.js index 592e94c2e..202e9578f 100644 --- a/js/src/dapps/chaindeploy/dapps/tokendeploy.js +++ b/js/src/dapps/chaindeploy/dapps/tokendeploy.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'tokendeploy'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/tokenreg.js b/js/src/dapps/chaindeploy/dapps/tokenreg.js index d8d81cd15..f7dcfd26e 100644 --- a/js/src/dapps/chaindeploy/dapps/tokenreg.js +++ b/js/src/dapps/chaindeploy/dapps/tokenreg.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'tokenreg'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/chaindeploy/dapps/web.js b/js/src/dapps/chaindeploy/dapps/web.js index 7fb6da5e0..ed3cf0623 100644 --- a/js/src/dapps/chaindeploy/dapps/web.js +++ b/js/src/dapps/chaindeploy/dapps/web.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import builtins from '~/config/dappsBuiltin.json'; +import builtins from '@parity/shared/config/dappsBuiltin.json'; const id = 'web'; const app = builtins.find((app) => app.url === id); diff --git a/js/src/dapps/dappreg/dappsStore.js b/js/src/dapps/dappreg/dappsStore.js index 20941e229..a5fed961f 100644 --- a/js/src/dapps/dappreg/dappsStore.js +++ b/js/src/dapps/dappreg/dappsStore.js @@ -18,9 +18,9 @@ import BigNumber from 'bignumber.js'; import { action, computed, observable, transaction } from 'mobx'; import { flatten } from 'lodash'; -import * as abis from '~/contracts/abi'; -import Contracts from '~/contracts'; -import builtinJson from '~/config/dappsBuiltin.json'; +import * as abis from '@parity/shared/contracts/abi'; +import Contracts from '@parity/shared/contracts'; +import builtinJson from '@parity/shared/config/dappsBuiltin.json'; import Dapp from './dappStore.js'; import { deleteDapp, registerDapp, updateDapp } from './utils'; diff --git a/js/src/dapps/githubhint/services.js b/js/src/dapps/githubhint/services.js index a4a4a6891..048fc6f14 100644 --- a/js/src/dapps/githubhint/services.js +++ b/js/src/dapps/githubhint/services.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import * as abis from '~/contracts/abi'; +import * as abis from '@parity/shared/contracts/abi'; + import { api } from './parity'; let defaultSubscriptionId; diff --git a/js/src/dapps/localtx/Application/application.spec.js b/js/src/dapps/localtx/Application/application.spec.js index 64d1d8872..a5e324b97 100644 --- a/js/src/dapps/localtx/Application/application.spec.js +++ b/js/src/dapps/localtx/Application/application.spec.js @@ -17,7 +17,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import '../../../environment/tests'; +import '@parity/shared/environment/tests'; import Application from './application'; diff --git a/js/src/dapps/localtx/Transaction/transaction.spec.js b/js/src/dapps/localtx/Transaction/transaction.spec.js index af2edf2d4..cc631e413 100644 --- a/js/src/dapps/localtx/Transaction/transaction.spec.js +++ b/js/src/dapps/localtx/Transaction/transaction.spec.js @@ -17,8 +17,8 @@ import React from 'react'; import { shallow } from 'enzyme'; -import '../../../environment/tests'; -import EthApi from '../../../api'; +import EthApi from '@parity/api'; +import '@parity/shared/environment/tests'; // Mock API for tests import * as Api from '../parity'; diff --git a/js/src/dapps/package.json b/js/src/dapps/package.json new file mode 100644 index 000000000..410bb2207 --- /dev/null +++ b/js/src/dapps/package.json @@ -0,0 +1,19 @@ +{ + "name": "@parity/dapps", + "description": "Parity dapps", + "version": "0.0.0", + "main": "index.js", + "author": "Parity Team ", + "maintainers": [], + "contributors": [], + "license": "GPL-3.0", + "repository": { + "type": "git", + "url": "git+https://github.com/paritytech/parity.git" + }, + "keywords": [], + "scripts": {}, + "devDependencies": {}, + "dependencies": {}, + "peerDependencies": {} +} diff --git a/js/src/dapps/registry/Application/application.js b/js/src/dapps/registry/Application/application.js index 7857b1ad1..09cf2d7f8 100644 --- a/js/src/dapps/registry/Application/application.js +++ b/js/src/dapps/registry/Application/application.js @@ -22,7 +22,8 @@ const muiTheme = getMuiTheme(lightBaseTheme); import CircularProgress from 'material-ui/CircularProgress'; import { Card, CardText } from 'material-ui/Card'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { api } from '../parity'; import styles from './application.css'; diff --git a/js/src/dapps/registry/Container.js b/js/src/dapps/registry/Container.js index 6a945a99c..4381f4382 100644 --- a/js/src/dapps/registry/Container.js +++ b/js/src/dapps/registry/Container.js @@ -18,7 +18,7 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; import Application from './Application'; import * as actions from './actions'; diff --git a/js/src/dapps/registry/Lookup/lookup.js b/js/src/dapps/registry/Lookup/lookup.js index 74b894816..c13267082 100644 --- a/js/src/dapps/registry/Lookup/lookup.js +++ b/js/src/dapps/registry/Lookup/lookup.js @@ -25,7 +25,7 @@ import DropDownMenu from 'material-ui/DropDownMenu'; import MenuItem from 'material-ui/MenuItem'; import keycode from 'keycode'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; import Address from '../ui/address.js'; import renderImage from '../ui/image.js'; diff --git a/js/src/dapps/registry/Names/names.js b/js/src/dapps/registry/Names/names.js index b6e629d39..44e33b8da 100644 --- a/js/src/dapps/registry/Names/names.js +++ b/js/src/dapps/registry/Names/names.js @@ -24,7 +24,8 @@ import MenuItem from 'material-ui/MenuItem'; import RaisedButton from 'material-ui/RaisedButton'; import CheckIcon from 'material-ui/svg-icons/navigation/check'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { fromWei } from '../parity.js'; import { clearError, reserve, drop } from './actions'; diff --git a/js/src/dapps/registry/Records/records.js b/js/src/dapps/registry/Records/records.js index e1deda6cd..c0f61585c 100644 --- a/js/src/dapps/registry/Records/records.js +++ b/js/src/dapps/registry/Records/records.js @@ -24,7 +24,8 @@ import MenuItem from 'material-ui/MenuItem'; import RaisedButton from 'material-ui/RaisedButton'; import SaveIcon from 'material-ui/svg-icons/content/save'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { clearError, update } from './actions'; import styles from './records.css'; diff --git a/js/src/dapps/registry/Reverse/reverse.js b/js/src/dapps/registry/Reverse/reverse.js index a17f9a22c..3197e56df 100644 --- a/js/src/dapps/registry/Reverse/reverse.js +++ b/js/src/dapps/registry/Reverse/reverse.js @@ -21,7 +21,8 @@ import { Card, CardHeader, CardText, TextField, DropDownMenu, MenuItem, RaisedButton } from 'material-ui'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { AddIcon, CheckIcon } from '~/ui/Icons'; import { clearError, confirm, propose } from './actions'; import styles from './reverse.css'; diff --git a/js/src/dapps/registry/actions.js b/js/src/dapps/registry/actions.js index ddb0b04b1..4642c2967 100644 --- a/js/src/dapps/registry/actions.js +++ b/js/src/dapps/registry/actions.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; import { api } from './parity.js'; import * as addresses from './addresses/actions.js'; diff --git a/js/src/dapps/registry/ui/address.js b/js/src/dapps/registry/ui/address.js index a01811fc4..2bf96f2e7 100644 --- a/js/src/dapps/registry/ui/address.js +++ b/js/src/dapps/registry/ui/address.js @@ -17,10 +17,11 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import Hash from './hash'; import etherscanUrl from '../util/etherscan-url'; import IdentityIcon from '../IdentityIcon'; -import { nullableProptype } from '~/util/proptypes'; import styles from './address.css'; diff --git a/js/src/dapps/registry/ui/image.js b/js/src/dapps/registry/ui/image.js index 3f0a90abe..8f8e4d556 100644 --- a/js/src/dapps/registry/ui/image.js +++ b/js/src/dapps/registry/ui/image.js @@ -16,7 +16,7 @@ import React from 'react'; -import { parityNode } from '../../../environment'; +import { parityNode } from '@parity/shared/environment'; const styles = { padding: '.5em', diff --git a/js/src/dapps/signaturereg/services.js b/js/src/dapps/signaturereg/services.js index 9c01e49fb..86a3bd81a 100644 --- a/js/src/dapps/signaturereg/services.js +++ b/js/src/dapps/signaturereg/services.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import * as abis from '~/contracts/abi'; +import * as abis from '@parity/shared/contracts/abi'; + import { api } from './parity'; const sortEvents = (a, b) => b.blockNumber.cmp(a.blockNumber) || b.logIndex.cmp(a.logIndex); diff --git a/js/src/dapps/tokendeploy/Transfer/Send/send.js b/js/src/dapps/tokendeploy/Transfer/Send/send.js index 9595e2045..35337f42a 100644 --- a/js/src/dapps/tokendeploy/Transfer/Send/send.js +++ b/js/src/dapps/tokendeploy/Transfer/Send/send.js @@ -17,7 +17,7 @@ import BigNumber from 'bignumber.js'; import React, { Component, PropTypes } from 'react'; -import { eip20 } from '~/contracts/abi'; +import { eip20 } from '@parity/shared/contracts/abi'; import { api } from '../../parity'; import { loadBalances } from '../../services'; diff --git a/js/src/dapps/tokendeploy/services.js b/js/src/dapps/tokendeploy/services.js index 6cfeff05f..b5817c380 100644 --- a/js/src/dapps/tokendeploy/services.js +++ b/js/src/dapps/tokendeploy/services.js @@ -17,7 +17,8 @@ import BigNumber from 'bignumber.js'; import { url as etherscanUrl } from '~/3rdparty/etherscan/links'; -import * as abis from '~/contracts/abi'; +import * as abis from '@parity/shared/contracts/abi'; + import { api } from './parity'; let managerInstance; diff --git a/js/src/dapps/tokenreg/Status/actions.js b/js/src/dapps/tokenreg/Status/actions.js index deb473d9b..22c99a5b5 100644 --- a/js/src/dapps/tokenreg/Status/actions.js +++ b/js/src/dapps/tokenreg/Status/actions.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; import { loadToken, setTokenPending, deleteToken, setTokenData } from '../Tokens/actions'; import { api } from '../parity'; diff --git a/js/src/dapps/tokenreg/Tokens/Token/token.js b/js/src/dapps/tokenreg/Tokens/Token/token.js index 5ea50535c..b1fa26891 100644 --- a/js/src/dapps/tokenreg/Tokens/Token/token.js +++ b/js/src/dapps/tokenreg/Tokens/Token/token.js @@ -30,7 +30,7 @@ import styles from './token.css'; import { metaDataKeys } from '../../constants'; import { api } from '../../parity'; -import { parityNode } from '../../../../environment'; +import { parityNode } from '@parity/shared/environment'; export default class Token extends Component { static propTypes = { diff --git a/js/src/dapps/tokenreg/utils.js b/js/src/dapps/tokenreg/utils.js index 82d71a6d0..315f097f7 100644 --- a/js/src/dapps/tokenreg/utils.js +++ b/js/src/dapps/tokenreg/utils.js @@ -16,7 +16,7 @@ import { api } from './parity'; -import { eip20 as eip20Abi } from '~/contracts/abi'; +import { eip20 as eip20Abi } from '@parity/shared/contracts/abi'; export const INVALID_URL_HASH = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; diff --git a/js/src/jsonrpc/interfaces/parity.js b/js/src/jsonrpc/interfaces/parity.js index 797052037..6ab5ea212 100644 --- a/js/src/jsonrpc/interfaces/parity.js +++ b/js/src/jsonrpc/interfaces/parity.js @@ -296,19 +296,6 @@ export default { } }, - getBlockHeaderByNumber: { - section: SECTION_NET, - desc: 'Returns block header information by number (same as eth_getBlockByNumber without transactions and uncles)', - params: [ - { - type: BlockNumber, - desc: 'integer of a block number, or the string `\'earliest\'`, `\'latest\'` or `\'pending\'`, as in the [default block parameter](#the-default-block-parameter).', - example: fromDecimal(436) - } - ], - returns: 'See [eth_getBlockByHash](#eth_getblockbyhash) (without transactions and uncles)' - }, - getVaultMeta: { section: SECTION_VAULT, desc: 'Returns the metadata for a specific vault', @@ -1927,5 +1914,87 @@ export default { desc: 'Message signature.', example: '0x1d9e33a8cf8bfc089a172bca01da462f9e359c6cb1b0f29398bc884e4d18df4f78588aee4fb5cc067ca62d2abab995e0bba29527be6ac98105b0320020a2efaf00' } + }, + + composeTransaction: { + desc: 'Given partial transaction request produces transaction with all fields filled in. Such transaction can be then signed externally.', + params: [ + { + type: TransactionRequest, + desc: 'see [`eth_sendTransaction`](JSONRPC-eth-module#eth_sendtransaction).', + format: 'inputCallFormatter', + example: { + from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', + to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567', + value: fromDecimal(2441406250) + } + } + ], + returns: { + type: Object, + desc: 'Transaction object (same as the parameter) with missing optional fields filled in by defaults.', + example: { + condition: null, + data: '0x', + from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', + gas: '0xe57e0', + gasPrice: '0x4a817c800', + nonce: '0x0', + to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567', + value: '0x9184e72a' + } + } + }, + + getBlockHeaderByNumber: { + desc: 'Get block header. Same as [`eth_getBlockByNumber`](JSONRPC-eth-module#eth_getblockbynumber) but without uncles and transactions.', + params: [ + { + type: BlockNumber, + desc: 'integer of a block number, or the string `\'earliest\'`, `\'latest\'` or `\'pending\'`, as in the [default block parameter](#the-default-block-parameter).', + example: fromDecimal(436) + } + ], + returns: { + type: Object, + desc: 'Block header', + example: { + author: '0xbb7b8287f3f0a933474a79eae42cbca977791171', + difficulty: '0x4ea3f27bc', + extraData: '0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32', + gasLimit: '0x1388', + gasUsed: '0x0', + hash: '0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae', + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + miner: '0xbb7b8287f3f0a933474a79eae42cbca977791171', + mixHash: '0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843', + nonce: '0x689056015818adbe', + number: '0x1b4', + parentHash: '0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54', + receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + sealFields: ['0xa04fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843', '0x88689056015818adbe'], + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: '0x21b', + stateRoot: '0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d', + timestamp: '0x55ba467c', + transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' + } + } + }, + + cidV0: { + desc: 'Compute a v0 IPFS Content ID from protobuf encoded bytes.', + params: [ + { + type: Data, + desc: 'to encode.', + example: '0x666f6f626172' + } + ], + returns: { + type: String, + desc: 'Base58 encoded CID', + example: 'QmSbFjqjd6nFwNHqsBCC7SK8GShGcayLUEtysJjNGhZAnC' + } } }; diff --git a/js/src/secureApi.js b/js/src/secureApi.js index 1c288a09f..0eccaafd1 100644 --- a/js/src/secureApi.js +++ b/js/src/secureApi.js @@ -18,7 +18,7 @@ import { uniq } from 'lodash'; import store from 'store'; import Api from '@parity/api'; -import { LOG_KEYS, getLogger } from '~/config'; +import { LOG_KEYS, getLogger } from '@parity/shared/config'; const log = getLogger(LOG_KEYS.Signer); diff --git a/js/src/serviceWorker.js b/js/src/serviceWorker.js index 5bdcb4dab..cf53dcd46 100644 --- a/js/src/serviceWorker.js +++ b/js/src/serviceWorker.js @@ -16,13 +16,11 @@ import toolbox from 'sw-toolbox'; -toolbox.precache(self.serviceWorkerOption.assets); - /** * Cache the SOLC files : if not available, make a network request */ -toolbox.router.any(/raw.githubusercontent.com\/ethereum\/solc-bin(.+)list\.json$/, toolbox.cacheFirst); -toolbox.router.any(/raw.githubusercontent.com\/ethereum\/solc-bin(.+)soljson(.+)\.js$/, toolbox.cacheFirst); +toolbox.router.any(/rawgit.com\/ethereum\/solc-bin(.+)list\.json$/, toolbox.networkFirst); +toolbox.router.any(/rawgit.com\/ethereum\/solc-bin(.+)soljson(.+)\.js$/, toolbox.cacheFirst); self.addEventListener('install', (event) => { event.waitUntil(self.skipWaiting()); diff --git a/js/src/config/dappsBuiltin.json b/js/src/shared/config/dappsBuiltin.json similarity index 100% rename from js/src/config/dappsBuiltin.json rename to js/src/shared/config/dappsBuiltin.json diff --git a/js/src/config/dappsViews.json b/js/src/shared/config/dappsViews.json similarity index 100% rename from js/src/config/dappsViews.json rename to js/src/shared/config/dappsViews.json diff --git a/js/src/config/index.js b/js/src/shared/config/index.js similarity index 100% rename from js/src/config/index.js rename to js/src/shared/config/index.js diff --git a/js/src/contracts/abi/badgereg.json b/js/src/shared/contracts/abi/badgereg.json similarity index 100% rename from js/src/contracts/abi/badgereg.json rename to js/src/shared/contracts/abi/badgereg.json diff --git a/js/src/contracts/abi/basiccoin.json b/js/src/shared/contracts/abi/basiccoin.json similarity index 100% rename from js/src/contracts/abi/basiccoin.json rename to js/src/shared/contracts/abi/basiccoin.json diff --git a/js/src/contracts/abi/basiccoinmanager.json b/js/src/shared/contracts/abi/basiccoinmanager.json similarity index 100% rename from js/src/contracts/abi/basiccoinmanager.json rename to js/src/shared/contracts/abi/basiccoinmanager.json diff --git a/js/src/contracts/abi/certifier.json b/js/src/shared/contracts/abi/certifier.json similarity index 100% rename from js/src/contracts/abi/certifier.json rename to js/src/shared/contracts/abi/certifier.json diff --git a/js/src/contracts/abi/dappreg.json b/js/src/shared/contracts/abi/dappreg.json similarity index 100% rename from js/src/contracts/abi/dappreg.json rename to js/src/shared/contracts/abi/dappreg.json diff --git a/js/src/contracts/abi/eip20.json b/js/src/shared/contracts/abi/eip20.json similarity index 100% rename from js/src/contracts/abi/eip20.json rename to js/src/shared/contracts/abi/eip20.json diff --git a/js/src/contracts/abi/email-verification.json b/js/src/shared/contracts/abi/email-verification.json similarity index 100% rename from js/src/contracts/abi/email-verification.json rename to js/src/shared/contracts/abi/email-verification.json diff --git a/js/src/contracts/abi/gavcoin.json b/js/src/shared/contracts/abi/gavcoin.json similarity index 100% rename from js/src/contracts/abi/gavcoin.json rename to js/src/shared/contracts/abi/gavcoin.json diff --git a/js/src/contracts/abi/githubhint.json b/js/src/shared/contracts/abi/githubhint.json similarity index 100% rename from js/src/contracts/abi/githubhint.json rename to js/src/shared/contracts/abi/githubhint.json diff --git a/js/src/contracts/abi/index.js b/js/src/shared/contracts/abi/index.js similarity index 100% rename from js/src/contracts/abi/index.js rename to js/src/shared/contracts/abi/index.js diff --git a/js/src/contracts/abi/old-wallet.json b/js/src/shared/contracts/abi/old-wallet.json similarity index 100% rename from js/src/contracts/abi/old-wallet.json rename to js/src/shared/contracts/abi/old-wallet.json diff --git a/js/src/contracts/abi/owned.json b/js/src/shared/contracts/abi/owned.json similarity index 100% rename from js/src/contracts/abi/owned.json rename to js/src/shared/contracts/abi/owned.json diff --git a/js/src/contracts/abi/registry.json b/js/src/shared/contracts/abi/registry.json similarity index 100% rename from js/src/contracts/abi/registry.json rename to js/src/shared/contracts/abi/registry.json diff --git a/js/src/contracts/abi/registry2.json b/js/src/shared/contracts/abi/registry2.json similarity index 100% rename from js/src/contracts/abi/registry2.json rename to js/src/shared/contracts/abi/registry2.json diff --git a/js/src/contracts/abi/signaturereg.json b/js/src/shared/contracts/abi/signaturereg.json similarity index 100% rename from js/src/contracts/abi/signaturereg.json rename to js/src/shared/contracts/abi/signaturereg.json diff --git a/js/src/contracts/abi/sms-verification.json b/js/src/shared/contracts/abi/sms-verification.json similarity index 100% rename from js/src/contracts/abi/sms-verification.json rename to js/src/shared/contracts/abi/sms-verification.json diff --git a/js/src/contracts/abi/tokenreg.json b/js/src/shared/contracts/abi/tokenreg.json similarity index 100% rename from js/src/contracts/abi/tokenreg.json rename to js/src/shared/contracts/abi/tokenreg.json diff --git a/js/src/contracts/abi/wallet.json b/js/src/shared/contracts/abi/wallet.json similarity index 100% rename from js/src/contracts/abi/wallet.json rename to js/src/shared/contracts/abi/wallet.json diff --git a/js/src/contracts/badgereg.js b/js/src/shared/contracts/badgereg.js similarity index 100% rename from js/src/contracts/badgereg.js rename to js/src/shared/contracts/badgereg.js diff --git a/js/src/contracts/code/index.js b/js/src/shared/contracts/code/index.js similarity index 100% rename from js/src/contracts/code/index.js rename to js/src/shared/contracts/code/index.js diff --git a/js/src/contracts/code/wallet.js b/js/src/shared/contracts/code/wallet.js similarity index 100% rename from js/src/contracts/code/wallet.js rename to js/src/shared/contracts/code/wallet.js diff --git a/js/src/contracts/contracts.js b/js/src/shared/contracts/contracts.js similarity index 100% rename from js/src/contracts/contracts.js rename to js/src/shared/contracts/contracts.js diff --git a/js/src/contracts/dappreg.js b/js/src/shared/contracts/dappreg.js similarity index 100% rename from js/src/contracts/dappreg.js rename to js/src/shared/contracts/dappreg.js diff --git a/js/src/contracts/githubhint.js b/js/src/shared/contracts/githubhint.js similarity index 100% rename from js/src/contracts/githubhint.js rename to js/src/shared/contracts/githubhint.js diff --git a/js/src/contracts/githubhint.spec.js b/js/src/shared/contracts/githubhint.spec.js similarity index 100% rename from js/src/contracts/githubhint.spec.js rename to js/src/shared/contracts/githubhint.spec.js diff --git a/js/src/contracts/index.js b/js/src/shared/contracts/index.js similarity index 100% rename from js/src/contracts/index.js rename to js/src/shared/contracts/index.js diff --git a/js/src/contracts/registry.js b/js/src/shared/contracts/registry.js similarity index 100% rename from js/src/contracts/registry.js rename to js/src/shared/contracts/registry.js diff --git a/js/src/contracts/registry.spec.js b/js/src/shared/contracts/registry.spec.js similarity index 100% rename from js/src/contracts/registry.spec.js rename to js/src/shared/contracts/registry.spec.js diff --git a/js/src/contracts/signaturereg.js b/js/src/shared/contracts/signaturereg.js similarity index 100% rename from js/src/contracts/signaturereg.js rename to js/src/shared/contracts/signaturereg.js diff --git a/js/src/contracts/snippets/enhanced-wallet.sol b/js/src/shared/contracts/snippets/enhanced-wallet.sol similarity index 100% rename from js/src/contracts/snippets/enhanced-wallet.sol rename to js/src/shared/contracts/snippets/enhanced-wallet.sol diff --git a/js/src/contracts/snippets/human-standard-token.sol b/js/src/shared/contracts/snippets/human-standard-token.sol similarity index 100% rename from js/src/contracts/snippets/human-standard-token.sol rename to js/src/shared/contracts/snippets/human-standard-token.sol diff --git a/js/src/contracts/snippets/standard-token.sol b/js/src/shared/contracts/snippets/standard-token.sol similarity index 100% rename from js/src/contracts/snippets/standard-token.sol rename to js/src/shared/contracts/snippets/standard-token.sol diff --git a/js/src/contracts/snippets/token.sol b/js/src/shared/contracts/snippets/token.sol similarity index 100% rename from js/src/contracts/snippets/token.sol rename to js/src/shared/contracts/snippets/token.sol diff --git a/js/src/contracts/snippets/wallet.sol b/js/src/shared/contracts/snippets/wallet.sol similarity index 100% rename from js/src/contracts/snippets/wallet.sol rename to js/src/shared/contracts/snippets/wallet.sol diff --git a/js/src/contracts/tokenreg.js b/js/src/shared/contracts/tokenreg.js similarity index 100% rename from js/src/contracts/tokenreg.js rename to js/src/shared/contracts/tokenreg.js diff --git a/js/src/contracts/verification.js b/js/src/shared/contracts/verification.js similarity index 100% rename from js/src/contracts/verification.js rename to js/src/shared/contracts/verification.js diff --git a/js/src/environment/empty.js b/js/src/shared/environment/empty.js similarity index 100% rename from js/src/environment/empty.js rename to js/src/shared/environment/empty.js diff --git a/js/src/environment/index.js b/js/src/shared/environment/index.js similarity index 100% rename from js/src/environment/index.js rename to js/src/shared/environment/index.js diff --git a/js/src/environment/integration-tests/fake-backend.js b/js/src/shared/environment/integration-tests/fake-backend.js similarity index 100% rename from js/src/environment/integration-tests/fake-backend.js rename to js/src/shared/environment/integration-tests/fake-backend.js diff --git a/js/src/environment/integration-tests/index.js b/js/src/shared/environment/integration-tests/index.js similarity index 100% rename from js/src/environment/integration-tests/index.js rename to js/src/shared/environment/integration-tests/index.js diff --git a/js/src/environment/perf-debug/index.js b/js/src/shared/environment/perf-debug/index.js similarity index 100% rename from js/src/environment/perf-debug/index.js rename to js/src/shared/environment/perf-debug/index.js diff --git a/js/src/environment/perf-debug/why-update.js b/js/src/shared/environment/perf-debug/why-update.js similarity index 100% rename from js/src/environment/perf-debug/why-update.js rename to js/src/shared/environment/perf-debug/why-update.js diff --git a/js/src/environment/tests/index.js b/js/src/shared/environment/tests/index.js similarity index 100% rename from js/src/environment/tests/index.js rename to js/src/shared/environment/tests/index.js diff --git a/js/src/environment/tests/test-utils.js b/js/src/shared/environment/tests/test-utils.js similarity index 100% rename from js/src/environment/tests/test-utils.js rename to js/src/shared/environment/tests/test-utils.js diff --git a/js/src/mobx/hardwareStore.js b/js/src/shared/mobx/hardwareStore.js similarity index 100% rename from js/src/mobx/hardwareStore.js rename to js/src/shared/mobx/hardwareStore.js diff --git a/js/src/mobx/hardwareStore.spec.js b/js/src/shared/mobx/hardwareStore.spec.js similarity index 100% rename from js/src/mobx/hardwareStore.spec.js rename to js/src/shared/mobx/hardwareStore.spec.js diff --git a/js/src/mobx/historyStore.js b/js/src/shared/mobx/historyStore.js similarity index 100% rename from js/src/mobx/historyStore.js rename to js/src/shared/mobx/historyStore.js diff --git a/js/src/mobx/historyStore.spec.js b/js/src/shared/mobx/historyStore.spec.js similarity index 100% rename from js/src/mobx/historyStore.spec.js rename to js/src/shared/mobx/historyStore.spec.js diff --git a/js/src/shared/package.json b/js/src/shared/package.json new file mode 100644 index 000000000..e2637e95c --- /dev/null +++ b/js/src/shared/package.json @@ -0,0 +1,19 @@ +{ + "name": "@parity/shared", + "description": "Shared states and non-ui components for the Parity wallet", + "version": "0.0.0", + "main": "index.js", + "author": "Parity Team ", + "maintainers": [], + "contributors": [], + "license": "GPL-3.0", + "repository": { + "type": "git", + "url": "git+https://github.com/paritytech/parity.git" + }, + "keywords": [], + "scripts": {}, + "devDependencies": {}, + "dependencies": {}, + "peerDependencies": {} +} diff --git a/js/src/redux/actions.js b/js/src/shared/redux/actions.js similarity index 100% rename from js/src/redux/actions.js rename to js/src/shared/redux/actions.js diff --git a/js/src/redux/index.js b/js/src/shared/redux/index.js similarity index 100% rename from js/src/redux/index.js rename to js/src/shared/redux/index.js diff --git a/js/src/redux/middleware.js b/js/src/shared/redux/middleware.js similarity index 100% rename from js/src/redux/middleware.js rename to js/src/shared/redux/middleware.js diff --git a/js/src/redux/providers/apiActions.js b/js/src/shared/redux/providers/apiActions.js similarity index 100% rename from js/src/redux/providers/apiActions.js rename to js/src/shared/redux/providers/apiActions.js diff --git a/js/src/redux/providers/apiReducer.js b/js/src/shared/redux/providers/apiReducer.js similarity index 100% rename from js/src/redux/providers/apiReducer.js rename to js/src/shared/redux/providers/apiReducer.js diff --git a/js/src/redux/providers/balances.js b/js/src/shared/redux/providers/balances.js similarity index 99% rename from js/src/redux/providers/balances.js rename to js/src/shared/redux/providers/balances.js index a07385c20..57d9cb4fd 100644 --- a/js/src/redux/providers/balances.js +++ b/js/src/shared/redux/providers/balances.js @@ -17,12 +17,11 @@ import { throttle } from 'lodash'; import { padRight } from '@parity/api/util/format'; +import Contracts from '@parity/shared/contracts'; import { fetchBalances, fetchTokensBalances, queryTokensFilter } from './balancesActions'; import { loadTokens, fetchTokens } from './tokensActions'; -import Contracts from '~/contracts'; - let instance = null; export default class Balances { diff --git a/js/src/redux/providers/balancesActions.js b/js/src/shared/redux/providers/balancesActions.js similarity index 97% rename from js/src/redux/providers/balancesActions.js rename to js/src/shared/redux/providers/balancesActions.js index b4b250fdc..208060214 100644 --- a/js/src/redux/providers/balancesActions.js +++ b/js/src/shared/redux/providers/balancesActions.js @@ -19,9 +19,9 @@ import { push } from 'react-router-redux'; import { sha3 } from '@parity/api/util/sha3'; -import { notifyTransaction } from '~/util/notifications'; -import { ETH_TOKEN, fetchAccountsBalances } from '~/util/tokens'; -import { LOG_KEYS, getLogger } from '~/config'; +import { LOG_KEYS, getLogger } from '@parity/shared/config'; +import { notifyTransaction } from '@parity/shared/util/notifications'; +import { ETH_TOKEN, fetchAccountsBalances } from '@parity/shared/util/tokens'; const TRANSFER_SIGNATURE = sha3('Transfer(address,address,uint256)'); diff --git a/js/src/redux/providers/balancesReducer.js b/js/src/shared/redux/providers/balancesReducer.js similarity index 100% rename from js/src/redux/providers/balancesReducer.js rename to js/src/shared/redux/providers/balancesReducer.js diff --git a/js/src/redux/providers/certifications/actions.js b/js/src/shared/redux/providers/certifications/actions.js similarity index 100% rename from js/src/redux/providers/certifications/actions.js rename to js/src/shared/redux/providers/certifications/actions.js diff --git a/js/src/redux/providers/certifications/middleware.js b/js/src/shared/redux/providers/certifications/middleware.js similarity index 96% rename from js/src/redux/providers/certifications/middleware.js rename to js/src/shared/redux/providers/certifications/middleware.js index b494b75d2..ef661d438 100644 --- a/js/src/redux/providers/certifications/middleware.js +++ b/js/src/shared/redux/providers/certifications/middleware.js @@ -17,10 +17,9 @@ import { uniq, range, debounce } from 'lodash'; import Contract from '@parity/api/contract'; - -import { getLogger, LOG_KEYS } from '~/config'; -import Contracts from '~/contracts'; -import CertifierABI from '~/contracts/abi/certifier.json'; +import { getLogger, LOG_KEYS } from '@parity/shared/config'; +import Contracts from '@parity/shared/contracts'; +import CertifierABI from '@parity/shared/contracts/abi/certifier.json'; import { addCertification, removeCertification } from './actions'; @@ -128,7 +127,8 @@ export default class CertificationsMiddleware { return badgeReg.getContract() .then((badgeRegContract) => { logs = badgeRegContract.parseEventLogs(logs); - const ids = logs.map((log) => log.params.id.value.toNumber()); + + const ids = logs.map((log) => log.params && log.params.id.value.toNumber()); return fetchCertifiers(uniq(ids)); }); diff --git a/js/src/redux/providers/certifications/reducer.js b/js/src/shared/redux/providers/certifications/reducer.js similarity index 100% rename from js/src/redux/providers/certifications/reducer.js rename to js/src/shared/redux/providers/certifications/reducer.js diff --git a/js/src/redux/providers/chainMiddleware.js b/js/src/shared/redux/providers/chainMiddleware.js similarity index 100% rename from js/src/redux/providers/chainMiddleware.js rename to js/src/shared/redux/providers/chainMiddleware.js diff --git a/js/src/redux/providers/chainMiddleware.spec.js b/js/src/shared/redux/providers/chainMiddleware.spec.js similarity index 98% rename from js/src/redux/providers/chainMiddleware.spec.js rename to js/src/shared/redux/providers/chainMiddleware.spec.js index fcd4c4744..8e68dbcc5 100644 --- a/js/src/redux/providers/chainMiddleware.spec.js +++ b/js/src/shared/redux/providers/chainMiddleware.spec.js @@ -16,7 +16,8 @@ import sinon from 'sinon'; -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; + import { initialState as defaultNodeStatusState } from './statusReducer'; import ChainMiddleware from './chainMiddleware'; import { createWsApi } from '~/../test/e2e/ethapi'; diff --git a/js/src/redux/providers/index.js b/js/src/shared/redux/providers/index.js similarity index 100% rename from js/src/redux/providers/index.js rename to js/src/shared/redux/providers/index.js diff --git a/js/src/redux/providers/personal.js b/js/src/shared/redux/providers/personal.js similarity index 100% rename from js/src/redux/providers/personal.js rename to js/src/shared/redux/providers/personal.js diff --git a/js/src/redux/providers/personalActions.js b/js/src/shared/redux/providers/personalActions.js similarity index 97% rename from js/src/redux/providers/personalActions.js rename to js/src/shared/redux/providers/personalActions.js index 62d32048d..7febe4909 100644 --- a/js/src/redux/providers/personalActions.js +++ b/js/src/shared/redux/providers/personalActions.js @@ -17,14 +17,14 @@ import { isEqual, intersection } from 'lodash'; import Contract from '@parity/api/contract'; +import { wallet as WalletAbi } from '@parity/shared/contracts/abi'; +import WalletsUtils from '@parity/shared/util/wallets'; import BalancesProvider from './balances'; import { updateTokensFilter } from './balancesActions'; import { attachWallets } from './walletActions'; import MethodDecodingStore from '~/ui/MethodDecoding/methodDecodingStore'; -import WalletsUtils from '~/util/wallets'; -import { wallet as WalletAbi } from '~/contracts/abi'; export function personalAccountsInfo (accountsInfo) { const accounts = {}; diff --git a/js/src/redux/providers/personalReducer.js b/js/src/shared/redux/providers/personalReducer.js similarity index 100% rename from js/src/redux/providers/personalReducer.js rename to js/src/shared/redux/providers/personalReducer.js diff --git a/js/src/redux/providers/registry/actions.js b/js/src/shared/redux/providers/registry/actions.js similarity index 100% rename from js/src/redux/providers/registry/actions.js rename to js/src/shared/redux/providers/registry/actions.js diff --git a/js/src/redux/providers/registry/middleware.js b/js/src/shared/redux/providers/registry/middleware.js similarity index 95% rename from js/src/redux/providers/registry/middleware.js rename to js/src/shared/redux/providers/registry/middleware.js index 8d48d5cd7..b0a21038a 100644 --- a/js/src/redux/providers/registry/middleware.js +++ b/js/src/shared/redux/providers/registry/middleware.js @@ -16,10 +16,10 @@ import { debounce } from 'lodash'; import store from 'store'; -import Contracts from '~/contracts'; -import subscribeToEvents from '~/util/subscribe-to-events'; -import registryABI from '~/contracts/abi/registry.json'; +import Contracts from '@parity/shared/contracts'; +import registryABI from '@parity/shared/contracts/abi/registry.json'; +import subscribeToEvents from '@parity/shared/util/subscribe-to-events'; import { setReverse } from './actions'; diff --git a/js/src/redux/providers/registry/reducer.js b/js/src/shared/redux/providers/registry/reducer.js similarity index 100% rename from js/src/redux/providers/registry/reducer.js rename to js/src/shared/redux/providers/registry/reducer.js diff --git a/js/src/redux/providers/requestsActions.js b/js/src/shared/redux/providers/requestsActions.js similarity index 99% rename from js/src/redux/providers/requestsActions.js rename to js/src/shared/redux/providers/requestsActions.js index fedfabc5e..67e4ddbc0 100644 --- a/js/src/redux/providers/requestsActions.js +++ b/js/src/shared/redux/providers/requestsActions.js @@ -17,8 +17,8 @@ import BigNumber from 'bignumber.js'; import { outTransaction } from '@parity/api/format/output'; +import { trackRequest as trackRequestUtil, parseTransactionReceipt } from '@parity/shared/util/tx'; -import { trackRequest as trackRequestUtil, parseTransactionReceipt } from '~/util/tx'; import SavedRequests from '~/shell/Requests/savedRequests'; const savedRequests = new SavedRequests(); diff --git a/js/src/redux/providers/requestsActions.spec.js b/js/src/shared/redux/providers/requestsActions.spec.js similarity index 100% rename from js/src/redux/providers/requestsActions.spec.js rename to js/src/shared/redux/providers/requestsActions.spec.js diff --git a/js/src/redux/providers/requestsReducer.js b/js/src/shared/redux/providers/requestsReducer.js similarity index 100% rename from js/src/redux/providers/requestsReducer.js rename to js/src/shared/redux/providers/requestsReducer.js diff --git a/js/src/redux/providers/settings/actions.js b/js/src/shared/redux/providers/settings/actions.js similarity index 100% rename from js/src/redux/providers/settings/actions.js rename to js/src/shared/redux/providers/settings/actions.js diff --git a/js/src/redux/providers/settings/middleware.js b/js/src/shared/redux/providers/settings/middleware.js similarity index 100% rename from js/src/redux/providers/settings/middleware.js rename to js/src/shared/redux/providers/settings/middleware.js diff --git a/js/src/redux/providers/settings/reducers.js b/js/src/shared/redux/providers/settings/reducers.js similarity index 100% rename from js/src/redux/providers/settings/reducers.js rename to js/src/shared/redux/providers/settings/reducers.js diff --git a/js/src/redux/providers/signer.js b/js/src/shared/redux/providers/signer.js similarity index 100% rename from js/src/redux/providers/signer.js rename to js/src/shared/redux/providers/signer.js diff --git a/js/src/redux/providers/signerActions.js b/js/src/shared/redux/providers/signerActions.js similarity index 100% rename from js/src/redux/providers/signerActions.js rename to js/src/shared/redux/providers/signerActions.js diff --git a/js/src/redux/providers/signerMiddleware.js b/js/src/shared/redux/providers/signerMiddleware.js similarity index 98% rename from js/src/redux/providers/signerMiddleware.js rename to js/src/shared/redux/providers/signerMiddleware.js index 50a8d9078..3e4608f90 100644 --- a/js/src/redux/providers/signerMiddleware.js +++ b/js/src/shared/redux/providers/signerMiddleware.js @@ -17,12 +17,11 @@ import * as actions from './signerActions'; import { inHex } from '@parity/api/format/input'; +import HardwareStore from '@parity/shared/mobx/hardwareStore'; +import { Signer } from '@parity/shared/util/signer'; import { createSignedTx } from '~/shell/Signer/utils/qrscan'; -import HardwareStore from '~/mobx/hardwareStore'; -import { Signer } from '~/util/signer'; - export default class SignerMiddleware { constructor (api) { this._api = api; diff --git a/js/src/redux/providers/signerMiddleware.spec.js b/js/src/shared/redux/providers/signerMiddleware.spec.js similarity index 100% rename from js/src/redux/providers/signerMiddleware.spec.js rename to js/src/shared/redux/providers/signerMiddleware.spec.js diff --git a/js/src/redux/providers/signerReducer.js b/js/src/shared/redux/providers/signerReducer.js similarity index 100% rename from js/src/redux/providers/signerReducer.js rename to js/src/shared/redux/providers/signerReducer.js diff --git a/js/src/redux/providers/snackbarActions.js b/js/src/shared/redux/providers/snackbarActions.js similarity index 100% rename from js/src/redux/providers/snackbarActions.js rename to js/src/shared/redux/providers/snackbarActions.js diff --git a/js/src/redux/providers/snackbarReducer.js b/js/src/shared/redux/providers/snackbarReducer.js similarity index 100% rename from js/src/redux/providers/snackbarReducer.js rename to js/src/shared/redux/providers/snackbarReducer.js diff --git a/js/src/redux/providers/status.js b/js/src/shared/redux/providers/status.js similarity index 99% rename from js/src/redux/providers/status.js rename to js/src/shared/redux/providers/status.js index 53d0630a7..48ba52df3 100644 --- a/js/src/redux/providers/status.js +++ b/js/src/shared/redux/providers/status.js @@ -16,7 +16,8 @@ import { isEqual } from 'lodash'; -import { LOG_KEYS, getLogger } from '~/config'; +import { LOG_KEYS, getLogger } from '@parity/shared/config'; + import UpgradeStore from '~/shell/UpgradeParity/store'; import BalancesProvider from './balances'; diff --git a/js/src/redux/providers/statusActions.js b/js/src/shared/redux/providers/statusActions.js similarity index 100% rename from js/src/redux/providers/statusActions.js rename to js/src/shared/redux/providers/statusActions.js diff --git a/js/src/redux/providers/statusReducer.js b/js/src/shared/redux/providers/statusReducer.js similarity index 100% rename from js/src/redux/providers/statusReducer.js rename to js/src/shared/redux/providers/statusReducer.js diff --git a/js/src/redux/providers/tokensActions.js b/js/src/shared/redux/providers/tokensActions.js similarity index 93% rename from js/src/redux/providers/tokensActions.js rename to js/src/shared/redux/providers/tokensActions.js index 16b536e71..233c04fa1 100644 --- a/js/src/redux/providers/tokensActions.js +++ b/js/src/shared/redux/providers/tokensActions.js @@ -16,10 +16,11 @@ import { uniq } from 'lodash'; -import Contracts from '~/contracts'; -import { LOG_KEYS, getLogger } from '~/config'; +import { LOG_KEYS, getLogger } from '@parity/shared/config'; +import Contracts from '@parity/shared/contracts'; +import { fetchTokenIds, fetchTokenInfo } from '@parity/shared/util/tokens'; + import { IconCache } from '~/ui'; -import { fetchTokenIds, fetchTokenInfo } from '~/util/tokens'; import { updateTokensFilter } from './balancesActions'; diff --git a/js/src/redux/providers/tokensReducer.js b/js/src/shared/redux/providers/tokensReducer.js similarity index 94% rename from js/src/redux/providers/tokensReducer.js rename to js/src/shared/redux/providers/tokensReducer.js index e11fb41a3..2e8b90fa1 100644 --- a/js/src/redux/providers/tokensReducer.js +++ b/js/src/shared/redux/providers/tokensReducer.js @@ -16,7 +16,7 @@ import { handleActions } from 'redux-actions'; -import { ETH_TOKEN } from '~/util/tokens'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; const initialState = { [ ETH_TOKEN.id ]: ETH_TOKEN diff --git a/js/src/redux/providers/walletActions.js b/js/src/shared/redux/providers/walletActions.js similarity index 98% rename from js/src/redux/providers/walletActions.js rename to js/src/shared/redux/providers/walletActions.js index 4d5c902ae..2d5a79b29 100644 --- a/js/src/redux/providers/walletActions.js +++ b/js/src/shared/redux/providers/walletActions.js @@ -19,10 +19,9 @@ import { isEqual, uniq } from 'lodash'; import Contract from '@parity/api/contract'; import { ERROR_CODES } from '@parity/api/transport/error'; import { bytesToHex, toHex } from '@parity/api/util/format'; - -import { wallet as WALLET_ABI } from '~/contracts/abi'; -import { MAX_GAS_ESTIMATION } from '~/util/constants'; -import WalletsUtils from '~/util/wallets'; +import { wallet as WALLET_ABI } from '@parity/shared/contracts/abi'; +import { MAX_GAS_ESTIMATION } from '@parity/shared/util/constants'; +import WalletsUtils from '@parity/shared/util/wallets'; import { newError } from '~/ui/Errors/actions'; diff --git a/js/src/redux/providers/walletReducer.js b/js/src/shared/redux/providers/walletReducer.js similarity index 100% rename from js/src/redux/providers/walletReducer.js rename to js/src/shared/redux/providers/walletReducer.js diff --git a/js/src/redux/providers/worker.js b/js/src/shared/redux/providers/worker.js similarity index 100% rename from js/src/redux/providers/worker.js rename to js/src/shared/redux/providers/worker.js diff --git a/js/src/redux/providers/workerActions.js b/js/src/shared/redux/providers/workerActions.js similarity index 100% rename from js/src/redux/providers/workerActions.js rename to js/src/shared/redux/providers/workerActions.js diff --git a/js/src/redux/providers/workerReducer.js b/js/src/shared/redux/providers/workerReducer.js similarity index 100% rename from js/src/redux/providers/workerReducer.js rename to js/src/shared/redux/providers/workerReducer.js diff --git a/js/src/redux/providers/workerWrapper.js b/js/src/shared/redux/providers/workerWrapper.js similarity index 100% rename from js/src/redux/providers/workerWrapper.js rename to js/src/shared/redux/providers/workerWrapper.js diff --git a/js/src/redux/reducers.js b/js/src/shared/redux/reducers.js similarity index 100% rename from js/src/redux/reducers.js rename to js/src/shared/redux/reducers.js diff --git a/js/src/redux/store.js b/js/src/shared/redux/store.js similarity index 100% rename from js/src/redux/store.js rename to js/src/shared/redux/store.js diff --git a/js/src/redux/util.js b/js/src/shared/redux/util.js similarity index 100% rename from js/src/redux/util.js rename to js/src/shared/redux/util.js diff --git a/js/src/util/abi.js b/js/src/shared/util/abi.js similarity index 100% rename from js/src/util/abi.js rename to js/src/shared/util/abi.js diff --git a/js/src/util/constants.js b/js/src/shared/util/constants.js similarity index 100% rename from js/src/util/constants.js rename to js/src/shared/util/constants.js diff --git a/js/src/util/dapps.js b/js/src/shared/util/dapps.js similarity index 97% rename from js/src/util/dapps.js rename to js/src/shared/util/dapps.js index a89db51a7..2467058da 100644 --- a/js/src/util/dapps.js +++ b/js/src/shared/util/dapps.js @@ -18,12 +18,13 @@ import BigNumber from 'bignumber.js'; import { pick, range, uniq } from 'lodash'; import { bytesToHex } from '@parity/api/util/format'; +import builtinJson from '@parity/shared/config/dappsBuiltin.json'; +import viewsJson from '@parity/shared/config/dappsViews.json'; -import Contracts from '~/contracts'; -import builtinJson from '~/config/dappsBuiltin.json'; -import viewsJson from '~/config/dappsViews.json'; import { IconCache } from '~/ui'; +import Contracts from '../contracts'; + const builtinApps = [].concat( viewsJson.map((app) => { app.isView = true; diff --git a/js/src/util/notifications.js b/js/src/shared/util/notifications.js similarity index 100% rename from js/src/util/notifications.js rename to js/src/shared/util/notifications.js diff --git a/js/src/util/proptypes.js b/js/src/shared/util/proptypes.js similarity index 100% rename from js/src/util/proptypes.js rename to js/src/shared/util/proptypes.js diff --git a/js/src/util/signer.js b/js/src/shared/util/signer.js similarity index 100% rename from js/src/util/signer.js rename to js/src/shared/util/signer.js diff --git a/js/src/util/solidity.js b/js/src/shared/util/solidity.js similarity index 87% rename from js/src/util/solidity.js rename to js/src/shared/util/solidity.js index 120c2b736..7309e8072 100644 --- a/js/src/util/solidity.js +++ b/js/src/shared/util/solidity.js @@ -52,21 +52,9 @@ export default class SolidityUtils { static getCompiler (build) { const { longVersion, path } = build; - const URL = `https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/${path}`; + const URL = `https://cdn.rawgit.com/ethereum/solc-bin/gh-pages/bin/${path}`; const isWorker = typeof window !== 'object'; - if (isWorker) { - return new Promise((resolve, reject) => { - self.importScripts(URL); - - setTimeout(() => { - const compiler = solc(self.Module); - - return resolve(compiler); - }, 50); - }); - } - return fetch(URL) .then((r) => r.text()) .then((code) => { diff --git a/js/src/util/subscribe-to-events.js b/js/src/shared/util/subscribe-to-events.js similarity index 100% rename from js/src/util/subscribe-to-events.js rename to js/src/shared/util/subscribe-to-events.js diff --git a/js/src/util/subscribe-to-events.spec.js b/js/src/shared/util/subscribe-to-events.spec.js similarity index 100% rename from js/src/util/subscribe-to-events.spec.js rename to js/src/shared/util/subscribe-to-events.spec.js diff --git a/js/src/util/subscribe-to-events.test.js b/js/src/shared/util/subscribe-to-events.test.js similarity index 100% rename from js/src/util/subscribe-to-events.test.js rename to js/src/shared/util/subscribe-to-events.test.js diff --git a/js/src/util/tokens.js b/js/src/shared/util/tokens.js similarity index 100% rename from js/src/util/tokens.js rename to js/src/shared/util/tokens.js diff --git a/js/src/util/tx.js b/js/src/shared/util/tx.js similarity index 99% rename from js/src/util/tx.js rename to js/src/shared/util/tx.js index b56fc8b1f..67c1e3efc 100644 --- a/js/src/util/tx.js +++ b/js/src/shared/util/tx.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import WalletsUtils from '~/util/wallets'; +import WalletsUtils from './wallets'; export function trackRequest (api, options, statusCallback) { const { requestId, transactionHash } = options; diff --git a/js/src/util/validation.js b/js/src/shared/util/validation.js similarity index 100% rename from js/src/util/validation.js rename to js/src/shared/util/validation.js diff --git a/js/src/util/validation.spec.js b/js/src/shared/util/validation.spec.js similarity index 100% rename from js/src/util/validation.spec.js rename to js/src/shared/util/validation.spec.js diff --git a/js/src/util/wallets.js b/js/src/shared/util/wallets.js similarity index 98% rename from js/src/util/wallets.js rename to js/src/shared/util/wallets.js index 819698953..455ce2f62 100644 --- a/js/src/util/wallets.js +++ b/js/src/shared/util/wallets.js @@ -22,9 +22,9 @@ import Abi from '@parity/abi'; import Contract from '@parity/api/contract'; import { bytesToHex, toHex } from '@parity/api/util/format'; -import { validateAddress } from '~/util/validation'; -import WalletAbi from '~/contracts/abi/wallet.json'; -import OldWalletAbi from '~/contracts/abi/old-wallet.json'; +import WalletAbi from '../contracts/abi/wallet.json'; +import OldWalletAbi from '../contracts/abi/old-wallet.json'; +import { validateAddress } from './validation'; const LS_PENDING_CONTRACTS_KEY = '_parity::wallets::pendingContracts'; diff --git a/js/src/shell/Connection/connection.spec.js b/js/src/shell/Connection/connection.spec.js index cdf8f2b8d..aa7a5e391 100644 --- a/js/src/shell/Connection/connection.spec.js +++ b/js/src/shell/Connection/connection.spec.js @@ -57,7 +57,7 @@ function render (store) { return component; } -describe('views/Connection', () => { +describe('shell/Connection', () => { it('renders defaults', () => { expect(render()).to.be.ok; }); diff --git a/js/src/shell/Dapps/dappStore.spec.js b/js/src/shell/Dapps/dappStore.spec.js index b08e1f1dc..36740f9a7 100644 --- a/js/src/shell/Dapps/dappStore.spec.js +++ b/js/src/shell/Dapps/dappStore.spec.js @@ -18,7 +18,7 @@ import BigNumber from 'bignumber.js'; import sinon from 'sinon'; import localStore from 'store'; -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; import Store, { LS_KEY_DISPLAY } from './dappsStore'; @@ -80,7 +80,7 @@ function create () { return store; } -describe('views/Dapps/DappStore', () => { +describe('shell/Dapps/DappStore', () => { beforeEach(() => { stubGlobals(); }); diff --git a/js/src/shell/Dapps/dappsStore.js b/js/src/shell/Dapps/dappsStore.js index dd0b24311..74d0a86c8 100644 --- a/js/src/shell/Dapps/dappsStore.js +++ b/js/src/shell/Dapps/dappsStore.js @@ -18,12 +18,8 @@ import EventEmitter from 'eventemitter3'; import { action, computed, observable, transaction } from 'mobx'; import store from 'store'; -import Contracts from '~/contracts'; -import { - fetchBuiltinApps, fetchLocalApps, - fetchRegistryAppIds, fetchRegistryApp, - subscribeToChanges -} from '~/util/dapps'; +import Contracts from '@parity/shared/contracts'; +import { fetchBuiltinApps, fetchLocalApps, fetchRegistryAppIds, fetchRegistryApp, subscribeToChanges } from '@parity/shared/util/dapps'; const LS_KEY_DISPLAY = 'displayApps'; const LS_KEY_EXTERNAL_ACCEPT = 'acceptExternal'; diff --git a/js/src/shell/Extension/store.js b/js/src/shell/Extension/store.js index d1df2eb5b..a2fb5c7f4 100644 --- a/js/src/shell/Extension/store.js +++ b/js/src/shell/Extension/store.js @@ -21,7 +21,7 @@ import { action, computed, observable } from 'mobx'; import store from 'store'; import browser from 'useragent.js/lib/browser'; -import { DOMAIN } from '~/util/constants'; +import { DOMAIN } from '@parity/shared/util/constants'; const A_DAY = 24 * 60 * 60 * 1000; const NEXT_DISPLAY = '_parity::extensionWarning::nextDisplay'; diff --git a/js/src/shell/FirstRun/firstRun.js b/js/src/shell/FirstRun/firstRun.js index 6ca65978e..2d4e1e9a7 100644 --- a/js/src/shell/FirstRun/firstRun.js +++ b/js/src/shell/FirstRun/firstRun.js @@ -21,9 +21,9 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { createIdentityImg } from '@parity/api/util/identity'; +import { newError } from '@parity/shared/redux/actions'; import ParityLogo from '~/../assets/images/parity-logo-black-no-text.svg'; -import { newError } from '~/redux/actions'; import { Button, Portal } from '~/ui'; import { CheckIcon, DoneIcon, NextIcon, PrintIcon } from '~/ui/Icons'; diff --git a/js/src/shell/FirstRun/firstRun.spec.js b/js/src/shell/FirstRun/firstRun.spec.js index 14707dd5c..e9233261d 100644 --- a/js/src/shell/FirstRun/firstRun.spec.js +++ b/js/src/shell/FirstRun/firstRun.spec.js @@ -62,7 +62,7 @@ function render (props = { visible: true }) { return component; } -describe('modals/FirstRun', () => { +describe('shell/FirstRun', () => { it('renders defaults', () => { expect(render()).to.be.ok; }); diff --git a/js/src/shell/ParityBar/accountStore.spec.js b/js/src/shell/ParityBar/accountStore.spec.js index 16cebf9e1..59213c833 100644 --- a/js/src/shell/ParityBar/accountStore.spec.js +++ b/js/src/shell/ParityBar/accountStore.spec.js @@ -30,7 +30,7 @@ function create () { return store; } -describe('views/ParityBar/AccountStore', () => { +describe('shell/ParityBar/AccountStore', () => { beforeEach(() => { create(); }); diff --git a/js/src/shell/ParityBar/parityBar.js b/js/src/shell/ParityBar/parityBar.js index a5cd32c14..9b8fa8076 100644 --- a/js/src/shell/ParityBar/parityBar.js +++ b/js/src/shell/ParityBar/parityBar.js @@ -83,7 +83,10 @@ class ParityBar extends Component { dappsStore .on('loaded', (app) => { this.app = app; - this.loadPosition(); + + if (this.props.dapp) { + this.loadPosition(); + } }); if (this.props.dapp) { diff --git a/js/src/shell/ParityBar/parityBar.spec.js b/js/src/shell/ParityBar/parityBar.spec.js index 51f714fc4..c14e0e328 100644 --- a/js/src/shell/ParityBar/parityBar.spec.js +++ b/js/src/shell/ParityBar/parityBar.spec.js @@ -59,7 +59,7 @@ function render (props = {}, state = {}) { return component; } -describe('views/ParityBar', () => { +describe('shell/ParityBar', () => { beforeEach(() => { render({ dapp: true }); }); @@ -84,12 +84,6 @@ describe('views/ParityBar', () => { expect(bar.find('div')).not.to.have.length(0); }); - it('renders the Account selector button', () => { - const icon = bar.find('Button').first().props().icon; - - expect(icon.type.displayName).to.equal('Connect(IdentityIcon)'); - }); - it('renders the Parity button', () => { const label = shallow(bar.find('Button').at(1).props().label); @@ -157,10 +151,6 @@ describe('views/ParityBar', () => { instance.renderExpanded.restore(); }); - it('renders the bar on with opened === false', () => { - expect(component.find('Link[to="/apps"]')).to.have.length(1); - }); - it('renders expanded with opened === true', () => { expect(instance.renderExpanded).not.to.have.been.called; instance.setState({ opened: true }); diff --git a/js/src/shell/Requests/requests.js b/js/src/shell/Requests/requests.js index e53c049f9..072b373f6 100644 --- a/js/src/shell/Requests/requests.js +++ b/js/src/shell/Requests/requests.js @@ -20,7 +20,8 @@ import ReactDOM from 'react-dom'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { hideRequest } from '~/redux/providers/requestsActions'; +import { hideRequest } from '@parity/shared/redux/providers/requestsActions'; + import { MethodDecoding, IdentityIcon, Progress, ScrollableText, ShortenedHash } from '~/ui'; import styles from './requests.css'; diff --git a/js/src/shell/Requests/savedRequests.spec.js b/js/src/shell/Requests/savedRequests.spec.js index acf3adc39..6a62ecea5 100644 --- a/js/src/shell/Requests/savedRequests.spec.js +++ b/js/src/shell/Requests/savedRequests.spec.js @@ -40,7 +40,7 @@ function createApi (networkVersion) { }; } -describe('views/Application/Requests/savedRequests', () => { +describe('shell/Requests/savedRequests', () => { beforeEach((done) => { store.set(LS_REQUESTS_KEY, { [NETWORK_ID]: { diff --git a/js/src/shell/Signer/Embedded/embedded.js b/js/src/shell/Signer/Embedded/embedded.js index ce01e42b7..30d87571c 100644 --- a/js/src/shell/Signer/Embedded/embedded.js +++ b/js/src/shell/Signer/Embedded/embedded.js @@ -20,10 +20,12 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import Store from '../store'; -import * as RequestsActions from '~/redux/providers/signerActions'; +import * as RequestsActions from '@parity/shared/redux/providers/signerActions'; + import { Container } from '~/ui'; +import Store from '../store'; + import RequestPending from '../components/RequestPending'; import styles from './embedded.css'; diff --git a/js/src/shell/Signer/components/SignRequest/signRequest.js b/js/src/shell/Signer/components/SignRequest/signRequest.js index 705b89965..212716035 100644 --- a/js/src/shell/Signer/components/SignRequest/signRequest.js +++ b/js/src/shell/Signer/components/SignRequest/signRequest.js @@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import HardwareStore from '~/mobx/hardwareStore'; +import HardwareStore from '@parity/shared/mobx/hardwareStore'; import Account from '../Account'; import TransactionPendingForm from '../TransactionPendingForm'; diff --git a/js/src/shell/Signer/components/TransactionPending/transactionPending.js b/js/src/shell/Signer/components/TransactionPending/transactionPending.js index b9cc8f684..a9eb5bdeb 100644 --- a/js/src/shell/Signer/components/TransactionPending/transactionPending.js +++ b/js/src/shell/Signer/components/TransactionPending/transactionPending.js @@ -19,7 +19,8 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import HardwareStore from '~/mobx/hardwareStore'; +import HardwareStore from '@parity/shared/mobx/hardwareStore'; + import { Button, GasPriceEditor } from '~/ui'; import TransactionMainDetails from '../TransactionMainDetails'; diff --git a/js/src/shell/Snackbar/snackbar.js b/js/src/shell/Snackbar/snackbar.js index 585cbc6ac..5578370e5 100644 --- a/js/src/shell/Snackbar/snackbar.js +++ b/js/src/shell/Snackbar/snackbar.js @@ -18,9 +18,9 @@ import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { Snackbar as SnackbarUI } from '~/ui'; +import { closeSnackbar } from '@parity/shared/redux/providers/snackbarActions'; -import { closeSnackbar } from '~/redux/providers/snackbarActions'; +import { Snackbar as SnackbarUI } from '~/ui'; function Snackbar ({ closeSnackbar, cooldown = 3500, message, open = false }) { return ( diff --git a/js/src/shell/UpgradeParity/store.spec.js b/js/src/shell/UpgradeParity/store.spec.js index 894fb1cc8..0d883c6b2 100644 --- a/js/src/shell/UpgradeParity/store.spec.js +++ b/js/src/shell/UpgradeParity/store.spec.js @@ -18,7 +18,7 @@ import Store from './store'; let store; -describe('modals/UpgradeParity/store', () => { +describe('shell/UpgradeParity/store', () => { describe('@actions', () => { beforeEach(() => { store = new Store(); diff --git a/js/src/shell/embed.js b/js/src/shell/embed.js index 2543f6ad2..5d033fe5b 100644 --- a/js/src/shell/embed.js +++ b/js/src/shell/embed.js @@ -25,16 +25,16 @@ import ReactDOM from 'react-dom'; import injectTapEventPlugin from 'react-tap-event-plugin'; -import SecureApi from '~/secureApi'; -import ContractInstances from '~/contracts'; +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; +import { patchApi } from '@parity/shared/util/tx'; + +import SecureApi from '~/secureApi'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; -import { patchApi } from '~/util/tx'; - -import '~/environment'; +import '@parity/shared/environment'; import '~/../assets/fonts/Roboto/font.css'; import '~/../assets/fonts/RobotoMono/font.css'; diff --git a/js/src/shell/index.js b/js/src/shell/index.js index 49e0f68d9..401c66615 100644 --- a/js/src/shell/index.js +++ b/js/src/shell/index.js @@ -27,20 +27,24 @@ import injectTapEventPlugin from 'react-tap-event-plugin'; import { IndexRoute, Redirect, Route, Router, hashHistory } from 'react-router'; import qs from 'querystring'; -import SecureApi from '~/secureApi'; -import ContractInstances from '~/contracts'; +import builtinDapps from '@parity/shared/config/dappsBuiltin.json'; +import viewsDapps from '@parity/shared/config/dappsViews.json'; +import ContractInstances from '@parity/shared/contracts'; +import HistoryStore from '@parity/shared/mobx/historyStore'; +import { initStore } from '@parity/shared/redux'; +import { patchApi } from '@parity/shared/util/tx'; + +import '@parity/shared/environment'; + +import SecureApi from '~/secureApi'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; -import { patchApi } from '~/util/tx'; import Application from './Application'; import Dapp from './Dapp'; import Dapps from './Dapps'; -import '~/environment'; - injectTapEventPlugin(); if (process.env.NODE_ENV === 'development') { @@ -69,10 +73,6 @@ const store = initStore(api, hashHistory); window.secureApi = api; -import HistoryStore from '~/mobx/historyStore'; -import builtinDapps from '~/config/dappsBuiltin.json'; -import viewsDapps from '~/config/dappsViews.json'; - const dapps = [].concat(viewsDapps, builtinDapps); const dappsHistory = HistoryStore.get('dapps'); diff --git a/js/src/ui/AccountCard/accountCard.example.js b/js/src/ui/AccountCard/accountCard.example.js index 7fb829edd..a8e0db2c1 100644 --- a/js/src/ui/AccountCard/accountCard.example.js +++ b/js/src/ui/AccountCard/accountCard.example.js @@ -14,97 +14,95 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component } from 'react'; +import React from 'react'; import PlaygroundExample from '~/views/Playground/playgroundExample'; import AccountCard from './accountCard'; -export default class AccountCardExample extends Component { - render () { - const account = { - address: '0x639ba260535db072a41115c472830846e4e9ad0f', - description: 'This is a description for the main account', - meta: { - tags: [ 'important', 'zargo' ] - }, - name: 'Main Account' - }; +const account = { + address: '0x639ba260535db072a41115c472830846e4e9ad0f', + description: 'This is a description for the main account', + meta: { + tags: [ 'important', 'zargo' ] + }, + name: 'Main Account' +}; - const balance = { - tokens: [ - { - value: 100000000000000000000, - token: { - tag: 'ETH' - } - } - ] - }; +const balance = { + tokens: [ + { + value: 100000000000000000000, + token: { + tag: 'ETH' + } + } + ] +}; - const accountManyTags = { - ...account, - meta: { tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => `tag #${n}`) } - }; +const accountManyTags = { + ...account, + meta: { tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => `tag #${n}`) } +}; - const accountNoTags = { - ...account, - meta: { tags: [] } - }; +const accountNoTags = { + ...account, + meta: { tags: [] } +}; - return ( -
- +export default function AccountCardExample () { + return ( +
+ + + + + +
- +
+
- -
+ +
+ +
+
+ + +
+ +
+
+ + +
+
- - - -
+
- - - -
- -
-
- - -
-
- -
-
- -
-
-
-
- ); - } +
+
+
+ ); } diff --git a/js/src/ui/AccountCard/accountCard.spec.js b/js/src/ui/AccountCard/accountCard.spec.js index 318434605..bff5cf5f2 100644 --- a/js/src/ui/AccountCard/accountCard.spec.js +++ b/js/src/ui/AccountCard/accountCard.spec.js @@ -19,7 +19,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import sinon from 'sinon'; -import { ETH_TOKEN } from '~/util/tokens'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; import AccountCard from './'; @@ -109,7 +109,7 @@ describe('ui/AccountCard', () => { let icon; beforeEach(() => { - icon = component.find('Connect(IdentityIcon)'); + icon = component.find('IdentityIcon'); }); it('renders the icon', () => { diff --git a/js/src/ui/Actionbar/Import/import.js b/js/src/ui/Actionbar/Import/import.js index a447be4cb..a10486bf3 100644 --- a/js/src/ui/Actionbar/Import/import.js +++ b/js/src/ui/Actionbar/Import/import.js @@ -17,7 +17,7 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Button from '../../Button'; import FileSelect from '../../Form/FileSelect'; diff --git a/js/src/ui/Actionbar/actionbar.js b/js/src/ui/Actionbar/actionbar.js index 2564d7c10..cfec3cf2f 100644 --- a/js/src/ui/Actionbar/actionbar.js +++ b/js/src/ui/Actionbar/actionbar.js @@ -16,7 +16,7 @@ import React, { PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './actionbar.css'; diff --git a/js/src/ui/Balance/balance.js b/js/src/ui/Balance/balance.js index 8af5e2852..58ea6f554 100644 --- a/js/src/ui/Balance/balance.js +++ b/js/src/ui/Balance/balance.js @@ -117,10 +117,6 @@ function Balance ({ balance, className, showOnlyEth, tokens }) { ); } -Balance.contextTypes = { - api: PropTypes.object.isRequired -}; - Balance.propTypes = { balance: PropTypes.object.isRequired, tokens: PropTypes.object.isRequired, diff --git a/js/src/ui/Balance/balance.spec.js b/js/src/ui/Balance/balance.spec.js index 2f541e828..1972f2533 100644 --- a/js/src/ui/Balance/balance.spec.js +++ b/js/src/ui/Balance/balance.spec.js @@ -17,10 +17,13 @@ import BigNumber from 'bignumber.js'; import { shallow } from 'enzyme'; import React from 'react'; +import sinon from 'sinon'; import apiutil from '@parity/api/util'; -import { Balance } from './balance'; +import Balance from './balance'; + +const ADDRESS = '0x123456789abcdef0123456789abcdef0123456789abcdef'; const TOKENS = { 'eth': { tag: 'ETH' }, @@ -35,8 +38,26 @@ const BALANCE = { }; let api; +let store; let component; +function createStore () { + store = { + dispatch: sinon.stub(), + subscribe: sinon.stub(), + getState: () => { + return { + balances: { + [ADDRESS]: BALANCE + }, + tokens: TOKENS + }; + } + }; + + return store; +} + function createApi () { api = { dappsUrl: 'http://testDapps:1234/', @@ -47,25 +68,20 @@ function createApi () { } function render (props = {}) { - if (!props.balance) { - props.balance = BALANCE; - } - - if (!props.tokens) { - props.tokens = TOKENS; - } - - const api = createApi(); - component = shallow( , { - context: { api } + context: { + api: createApi(), + store: createStore() + } } - ); + ).find('Balance').shallow(); + console.log(component.debug()); return component; } @@ -84,13 +100,6 @@ describe('ui/Balance', () => { }); it('renders all the non-zero balances', () => { - expect(component.find('Connect(TokenImage)')).to.have.length(2); - }); - - describe('render specifiers', () => { - it('renders all the tokens with showZeroValues', () => { - render({ showZeroValues: true }); - expect(component.find('Connect(TokenImage)')).to.have.length(2); - }); + expect(component.find('TokenImage')).to.have.length(2); }); }); diff --git a/js/src/ui/Button/button.js b/js/src/ui/Button/button.js index 86bb1c96c..c9ad00187 100644 --- a/js/src/ui/Button/button.js +++ b/js/src/ui/Button/button.js @@ -17,7 +17,7 @@ import React, { PropTypes } from 'react'; import { Button as ButtonUI } from 'semantic-ui-react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; export default function Button ({ active, animated, basic, className, color, disabled, fullWidth, icon, label, onClick, primary, size, toggle }) { return ( diff --git a/js/src/ui/ConfirmDialog/confirmDialog.js b/js/src/ui/ConfirmDialog/confirmDialog.js index f6514d63d..6ca2a05a6 100644 --- a/js/src/ui/ConfirmDialog/confirmDialog.js +++ b/js/src/ui/ConfirmDialog/confirmDialog.js @@ -17,7 +17,7 @@ import React, { PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Button from '../Button'; import Portal from '../Portal'; diff --git a/js/src/ui/ConfirmDialog/confirmDialog.spec.js b/js/src/ui/ConfirmDialog/confirmDialog.spec.js index cdc1e8be8..88339926c 100644 --- a/js/src/ui/ConfirmDialog/confirmDialog.spec.js +++ b/js/src/ui/ConfirmDialog/confirmDialog.spec.js @@ -105,11 +105,6 @@ describe('ui/ConfirmDialog', () => { expect(buttons[1].props.label.props.id).to.equal('ui.confirmDialog.yes'); }); - it('renders default icons', () => { - expect(buttons[0].props.icon.type.displayName).to.equal('ContentClear'); - expect(buttons[1].props.icon.type.displayName).to.equal('NavigationCheck'); - }); - describe('overrides', () => { beforeEach(() => { render({ diff --git a/js/src/ui/Container/Title/Byline/byline.js b/js/src/ui/Container/Title/Byline/byline.js index 62d22570d..617467607 100644 --- a/js/src/ui/Container/Title/Byline/byline.js +++ b/js/src/ui/Container/Title/Byline/byline.js @@ -16,7 +16,7 @@ import React from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from '../title.css'; diff --git a/js/src/ui/Container/Title/Description/description.js b/js/src/ui/Container/Title/Description/description.js index 27aca973a..2d1a5a8d3 100644 --- a/js/src/ui/Container/Title/Description/description.js +++ b/js/src/ui/Container/Title/Description/description.js @@ -16,7 +16,7 @@ import React from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from '../title.css'; diff --git a/js/src/ui/Container/Title/title.js b/js/src/ui/Container/Title/title.js index 415796129..c2543a581 100644 --- a/js/src/ui/Container/Title/title.js +++ b/js/src/ui/Container/Title/title.js @@ -16,7 +16,7 @@ import React, { PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Byline from './Byline'; import Description from './Description'; diff --git a/js/src/ui/Container/Title/title.spec.js b/js/src/ui/Container/Title/title.spec.js index 45e91cbef..e699b7a19 100644 --- a/js/src/ui/Container/Title/title.spec.js +++ b/js/src/ui/Container/Title/title.spec.js @@ -40,7 +40,7 @@ describe('ui/Container/Title', () => { }); it('renders the specified byline', () => { - expect(render({ byline: 'bylineText' })).to.contain.text('bylineText'); + expect(render({ byline: 'bylineText' }).find('Byline').props().byline).to.equal('bylineText'); }); }); }); diff --git a/js/src/ui/Container/container.js b/js/src/ui/Container/container.js index 5e4eb52b1..9eed9a254 100644 --- a/js/src/ui/Container/container.js +++ b/js/src/ui/Container/container.js @@ -18,7 +18,7 @@ import React, { Component, PropTypes } from 'react'; import { Link } from 'react-router'; import { Card } from 'semantic-ui-react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import DappLink from '../DappLink'; import Title from './Title'; diff --git a/js/src/ui/CopyToClipboard/copyToClipboard.js b/js/src/ui/CopyToClipboard/copyToClipboard.js index 016730fce..cc18d1556 100644 --- a/js/src/ui/CopyToClipboard/copyToClipboard.js +++ b/js/src/ui/CopyToClipboard/copyToClipboard.js @@ -21,7 +21,7 @@ import Clipboard from 'react-copy-to-clipboard'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { showSnackbar } from '~/redux/providers/snackbarActions'; +import { showSnackbar } from '@parity/shared/redux/providers/snackbarActions'; import { CopyIcon } from '../Icons'; import Theme from '../Theme'; diff --git a/js/src/ui/CurrencySymbol/currencySymbol.example.js b/js/src/ui/CurrencySymbol/currencySymbol.example.js index c775a192f..770b6050c 100644 --- a/js/src/ui/CurrencySymbol/currencySymbol.example.js +++ b/js/src/ui/CurrencySymbol/currencySymbol.example.js @@ -14,38 +14,36 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component } from 'react'; +import React from 'react'; import PlaygroundExample from '~/views/Playground/playgroundExample'; import ConnectedCurrencySymbol, { CurrencySymbol } from './currencySymbol'; -export default class CurrencySymbolExample extends Component { - render () { - return ( -
- - - +export default function CurrencySymbolExample () { + return ( +
+ + + - - - + + + - - - + + + - - - -
- ); - } + + + +
+ ); } diff --git a/js/src/ui/DappLink/dappLink.js b/js/src/ui/DappLink/dappLink.js index a097a183a..feb8a1cc7 100644 --- a/js/src/ui/DappLink/dappLink.js +++ b/js/src/ui/DappLink/dappLink.js @@ -16,7 +16,7 @@ import React, { Component, PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './dappLink.css'; diff --git a/js/src/ui/Form/AddressSelect/addressSelect.js b/js/src/ui/Form/AddressSelect/addressSelect.js index 4b228a6c2..cb6883c33 100644 --- a/js/src/ui/Form/AddressSelect/addressSelect.js +++ b/js/src/ui/Form/AddressSelect/addressSelect.js @@ -23,14 +23,14 @@ import { observer } from 'mobx-react'; import TextFieldUnderline from 'material-ui/TextField/TextFieldUnderline'; import apiutil from '@parity/api/util'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; +import { validateAddress } from '@parity/shared/util/validation'; import AccountCard from '~/ui/AccountCard'; import CopyToClipboard from '~/ui/CopyToClipboard'; import InputAddress from '~/ui/Form/InputAddress'; import Loading from '~/ui/Loading'; import Portal from '~/ui/Portal'; -import { nodeOrStringProptype } from '~/util/proptypes'; -import { validateAddress } from '~/util/validation'; import AddressSelectStore from './addressSelectStore'; import styles from './addressSelect.css'; diff --git a/js/src/ui/Form/AddressSelect/addressSelectStore.js b/js/src/ui/Form/AddressSelect/addressSelectStore.js index 24cdf7c9f..d06c123d3 100644 --- a/js/src/ui/Form/AddressSelect/addressSelectStore.js +++ b/js/src/ui/Form/AddressSelect/addressSelectStore.js @@ -20,8 +20,7 @@ import { flatMap, uniqBy } from 'lodash'; import { FormattedMessage } from 'react-intl'; import { sha3 } from '@parity/api/util/sha3'; - -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; const ZERO = /^(0x)?0*$/; diff --git a/js/src/ui/Form/AutoComplete/autocomplete.js b/js/src/ui/Form/AutoComplete/autocomplete.js index 63b1e65fd..0e5667398 100644 --- a/js/src/ui/Form/AutoComplete/autocomplete.js +++ b/js/src/ui/Form/AutoComplete/autocomplete.js @@ -20,7 +20,7 @@ import { MenuItem, AutoComplete as MUIAutoComplete, Divider as MUIDivider } from import { PopoverAnimationVertical } from 'material-ui/Popover'; import React, { Component, PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './autocomplete.css'; diff --git a/js/src/ui/Form/Checkbox/checkbox.js b/js/src/ui/Form/Checkbox/checkbox.js index adf10592b..4f20f2014 100644 --- a/js/src/ui/Form/Checkbox/checkbox.js +++ b/js/src/ui/Form/Checkbox/checkbox.js @@ -17,7 +17,7 @@ import React, { PropTypes } from 'react'; import { Checkbox as SemCheckbox } from 'semantic-ui-react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; export default function Checkbox ({ checked = false, className, label, onClick, style }) { return ( diff --git a/js/src/ui/Form/FileSelect/fileSelect.js b/js/src/ui/Form/FileSelect/fileSelect.js index 18b2c8d8e..39bbfa4e5 100644 --- a/js/src/ui/Form/FileSelect/fileSelect.js +++ b/js/src/ui/Form/FileSelect/fileSelect.js @@ -18,7 +18,7 @@ import React, { Component, PropTypes } from 'react'; import Dropzone from 'react-dropzone'; import { FormattedMessage } from 'react-intl'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './fileSelect.css'; diff --git a/js/src/ui/Form/Input/input.js b/js/src/ui/Form/Input/input.js index 98acad855..0828b0a57 100644 --- a/js/src/ui/Form/Input/input.js +++ b/js/src/ui/Form/Input/input.js @@ -19,9 +19,9 @@ import { TextField } from 'material-ui'; import { noop } from 'lodash'; import keycode from 'keycode'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; -import CopyToClipboard from '../../CopyToClipboard'; +import CopyToClipboard from '~/ui/CopyToClipboard'; import styles from './input.css'; diff --git a/js/src/ui/Form/InputAddress/inputAddress.js b/js/src/ui/Form/InputAddress/inputAddress.js index a590beddd..65fb4ce7c 100644 --- a/js/src/ui/Form/InputAddress/inputAddress.js +++ b/js/src/ui/Form/InputAddress/inputAddress.js @@ -18,12 +18,11 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import util from '@parity/api/util'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; +import { isNullAddress } from '@parity/shared/util/validation'; -import { nodeOrStringProptype } from '~/util/proptypes'; -import { isNullAddress } from '~/util/validation'; - -import IdentityIcon from '../../IdentityIcon'; -import Input from '../Input'; +import IdentityIcon from '~/ui/IdentityIcon'; +import Input from '~/ui/Form/Input'; import styles from './inputAddress.css'; diff --git a/js/src/ui/Form/InputAddressSelect/inputAddressSelect.js b/js/src/ui/Form/InputAddressSelect/inputAddressSelect.js index 8199fece6..17e2f39e8 100644 --- a/js/src/ui/Form/InputAddressSelect/inputAddressSelect.js +++ b/js/src/ui/Form/InputAddressSelect/inputAddressSelect.js @@ -17,7 +17,7 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import AddressSelect from '../AddressSelect'; diff --git a/js/src/ui/Form/InputChip/inputChip.js b/js/src/ui/Form/InputChip/inputChip.js index 479f17da0..72896a628 100644 --- a/js/src/ui/Form/InputChip/inputChip.js +++ b/js/src/ui/Form/InputChip/inputChip.js @@ -20,7 +20,7 @@ import ChipInput from 'material-ui-chip-input'; import { blue300 } from 'material-ui/styles/colors'; import { uniq } from 'lodash'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './inputChip.css'; diff --git a/js/src/ui/Form/InputInline/inputInline.js b/js/src/ui/Form/InputInline/inputInline.js index 5736b7d39..dec0eb028 100644 --- a/js/src/ui/Form/InputInline/inputInline.js +++ b/js/src/ui/Form/InputInline/inputInline.js @@ -16,7 +16,7 @@ import React, { Component, PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Input from '../Input'; diff --git a/js/src/ui/Form/RadioButtons/radioButtons.js b/js/src/ui/Form/RadioButtons/radioButtons.js index bebe9c0f8..58c90df6f 100644 --- a/js/src/ui/Form/RadioButtons/radioButtons.js +++ b/js/src/ui/Form/RadioButtons/radioButtons.js @@ -17,7 +17,7 @@ import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'; import React, { Component, PropTypes } from 'react'; -import { arrayOrObjectProptype } from '~/util/proptypes'; +import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; import Label from '../Label'; import styles from './radioButtons.css'; diff --git a/js/src/ui/Form/Select/select.js b/js/src/ui/Form/Select/select.js index cb6e864b7..3edf583c2 100644 --- a/js/src/ui/Form/Select/select.js +++ b/js/src/ui/Form/Select/select.js @@ -17,7 +17,7 @@ import React, { Component, PropTypes } from 'react'; import { MenuItem, SelectField } from 'material-ui'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; // TODO: duplicated in Input const UNDERLINE_DISABLED = { diff --git a/js/src/ui/Form/TypedInput/typedInput.js b/js/src/ui/Form/TypedInput/typedInput.js index c3a31fe07..33a89531c 100644 --- a/js/src/ui/Form/TypedInput/typedInput.js +++ b/js/src/ui/Form/TypedInput/typedInput.js @@ -23,13 +23,13 @@ import IconButton from 'material-ui/IconButton'; import { fromWei, toWei } from '@parity/api/util/wei'; import { bytesToHex } from '@parity/api/util/format'; +import { ABI_TYPES, parseAbiType } from '@parity/shared/util/abi'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Input from '~/ui/Form/Input'; import InputAddressSelect from '~/ui/Form/InputAddressSelect'; import Select from '~/ui/Form/Select'; import { AddIcon, RemoveIcon } from '~/ui/Icons'; -import { ABI_TYPES, parseAbiType } from '~/util/abi'; -import { nodeOrStringProptype } from '~/util/proptypes'; import styles from './typedInput.css'; diff --git a/js/src/ui/Form/TypedInput/typedInput.spec.js b/js/src/ui/Form/TypedInput/typedInput.spec.js index 56d81b642..a552ca12b 100644 --- a/js/src/ui/Form/TypedInput/typedInput.spec.js +++ b/js/src/ui/Form/TypedInput/typedInput.spec.js @@ -18,7 +18,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import sinon from 'sinon'; -import { ABI_TYPES } from '~/util/abi'; +import { ABI_TYPES } from '@parity/shared/util/abi'; import TypedInput from './'; diff --git a/js/src/ui/GasPriceEditor/store.js b/js/src/ui/GasPriceEditor/store.js index a7a3b914b..d5187ed06 100644 --- a/js/src/ui/GasPriceEditor/store.js +++ b/js/src/ui/GasPriceEditor/store.js @@ -17,8 +17,8 @@ import BigNumber from 'bignumber.js'; import { action, computed, observable, transaction } from 'mobx'; -import { ERRORS, validatePositiveNumber } from '~/util/validation'; -import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '~/util/constants'; +import { ERRORS, validatePositiveNumber } from '@parity/shared/util/validation'; +import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '@parity/shared/util/constants'; const CONDITIONS = { NONE: 'none', diff --git a/js/src/ui/GasPriceEditor/store.spec.js b/js/src/ui/GasPriceEditor/store.spec.js index 4580748ea..b6d5612d5 100644 --- a/js/src/ui/GasPriceEditor/store.spec.js +++ b/js/src/ui/GasPriceEditor/store.spec.js @@ -17,8 +17,8 @@ import BigNumber from 'bignumber.js'; import sinon from 'sinon'; -import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '~/util/constants'; -import { ERRORS } from '~/util/validation'; +import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '@parity/shared/util/constants'; +import { ERRORS } from '@parity/shared/util/validation'; import GasPriceEditor from './gasPriceEditor'; import { CONDITIONS } from './store'; diff --git a/js/src/ui/IdentityIcon/identityIcon.js b/js/src/ui/IdentityIcon/identityIcon.js index 2efe1d7ab..ca849fc6b 100644 --- a/js/src/ui/IdentityIcon/identityIcon.js +++ b/js/src/ui/IdentityIcon/identityIcon.js @@ -17,8 +17,8 @@ import React, { Component, PropTypes } from 'react'; import { createIdentityImg } from '@parity/api/util/identity'; +import { isNullAddress } from '@parity/shared/util/validation'; -import { isNullAddress } from '~/util/validation'; import IconCache from '~/ui/IconCache'; import { CancelIcon, ContractIcon } from '~/ui/Icons'; @@ -42,6 +42,8 @@ export default class IdentityIcon extends Component { tiny: PropTypes.bool } + static iconCache = iconCache; + state = { iconsrc: '' } @@ -62,8 +64,8 @@ export default class IdentityIcon extends Component { const { api } = this.context; const { button, inline, tiny } = this.props; - if (iconCache[_address]) { - this.setState({ iconsrc: `${api.dappsUrl}${iconCache[_address]}` }); + if (iconCache.images[_address]) { + this.setState({ iconsrc: `${api.dappsUrl}${iconCache.images[_address]}` }); return; } diff --git a/js/src/ui/IdentityIcon/identityIcon.spec.js b/js/src/ui/IdentityIcon/identityIcon.spec.js index 985cde26e..b64d59716 100644 --- a/js/src/ui/IdentityIcon/identityIcon.spec.js +++ b/js/src/ui/IdentityIcon/identityIcon.spec.js @@ -18,14 +18,14 @@ import { shallow } from 'enzyme'; import React from 'react'; import IdentityIcon from './'; -import IconCache from '../IconCache'; const ADDRESS0 = '0x0000000000000000000000000000000000000000'; const ADDRESS1 = '0x0123456789012345678901234567890123456789'; const ADDRESS2 = '0x9876543210987654321098765432109876543210'; +IdentityIcon.iconCache.add(ADDRESS2, 'cachedImage', true); + let component; -let iconCache; let instance; function createApi () { @@ -35,7 +35,7 @@ function createApi () { } function render (props = {}) { - if (props && props.address === undefined) { + if (props.address === undefined) { props.address = ADDRESS1; } @@ -47,9 +47,6 @@ function render (props = {}) { instance = component.instance(); instance.componentDidMount(); - iconCache = IconCache.get(true); - iconCache.add(ADDRESS2, 'cachedImage'); - return component; } @@ -74,11 +71,11 @@ describe('ui/IdentityIcon', () => { }); it('renders an with no address specified', () => { - expect(render({ address: null }).find('ActionCode')).to.have.length(1); + expect(render({ address: null }).find('ContractIcon')).to.have.length(1); }); it('renders an with 0x00..00 address specified', () => { - expect(render({ address: ADDRESS0 }).find('ContentClear')).to.have.length(1); + expect(render({ address: ADDRESS0 }).find('CancelIcon')).to.have.length(1); }); }); diff --git a/js/src/ui/IdentityName/identityName.js b/js/src/ui/IdentityName/identityName.js index eccb65c61..92997351a 100644 --- a/js/src/ui/IdentityName/identityName.js +++ b/js/src/ui/IdentityName/identityName.js @@ -18,7 +18,8 @@ import React, { PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import { isNullAddress } from '~/util/validation'; +import { isNullAddress } from '@parity/shared/util/validation'; + import ShortenedHash from '../ShortenedHash'; const defaultName = ( diff --git a/js/src/ui/MethodDecoding/methodDecodingStore.js b/js/src/ui/MethodDecoding/methodDecodingStore.js index d16f33439..0fe72895b 100644 --- a/js/src/ui/MethodDecoding/methodDecodingStore.js +++ b/js/src/ui/MethodDecoding/methodDecodingStore.js @@ -14,11 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import Contracts from '~/contracts'; -import Abi from '~/abi'; -import * as abis from '~/contracts/abi'; - +import Abi from '@parity/abi'; import { decodeMethodInput } from '@parity/api/util/decode'; +import Contracts from '@parity/shared/contracts'; +import * as abis from '@parity/shared/contracts/abi'; const CONTRACT_CREATE = '0x60606040'; diff --git a/js/src/ui/Modal/Busy/busy.js b/js/src/ui/Modal/Busy/busy.js index 3c1720720..cbf191197 100644 --- a/js/src/ui/Modal/Busy/busy.js +++ b/js/src/ui/Modal/Busy/busy.js @@ -16,7 +16,7 @@ import React, { PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './busy.css'; diff --git a/js/src/ui/ModalBox/modalBox.js b/js/src/ui/ModalBox/modalBox.js index bfcfbe88a..58f942ced 100644 --- a/js/src/ui/ModalBox/modalBox.js +++ b/js/src/ui/ModalBox/modalBox.js @@ -16,7 +16,7 @@ import React, { PropTypes } from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import Body from './body'; import Summary from './summary'; diff --git a/js/src/ui/ModalBox/summary.js b/js/src/ui/ModalBox/summary.js index cb198c472..4adbf914c 100644 --- a/js/src/ui/ModalBox/summary.js +++ b/js/src/ui/ModalBox/summary.js @@ -16,7 +16,7 @@ import React from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './modalBox.css'; diff --git a/js/src/ui/Page/page.js b/js/src/ui/Page/page.js index 7de6d9d9f..9fe276154 100644 --- a/js/src/ui/Page/page.js +++ b/js/src/ui/Page/page.js @@ -17,7 +17,7 @@ import React, { PropTypes } from 'react'; import Actionbar from '../Actionbar'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './page.css'; diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index 4ae36ccf4..a31efdecc 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -20,7 +20,8 @@ import ReactPortal from 'react-portal'; import keycode from 'keycode'; import { noop } from 'lodash'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; + import { CloseIcon } from '~/ui/Icons'; import StackEventListener from '~/ui/StackEventListener'; import Title from '~/ui/Title'; diff --git a/js/src/ui/QrCode/qrCode.example.js b/js/src/ui/QrCode/qrCode.example.js index 6a92467a3..427cbfa39 100644 --- a/js/src/ui/QrCode/qrCode.example.js +++ b/js/src/ui/QrCode/qrCode.example.js @@ -14,50 +14,48 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component } from 'react'; +import React from 'react'; import PlaygroundExample from '~/views/Playground/playgroundExample'; import QrCode from './'; -export default class QrCodeExample extends Component { - render () { - return ( -
- - - +export default function QrCodeExample () { + return ( +
+ + + - - - + + + - - - + + + - - - + + + - - - -
- ); - } + + + +
+ ); } diff --git a/js/src/ui/SectionList/Overlay/overlay.js b/js/src/ui/SectionList/Overlay/overlay.js index 087d3fbb0..95a6f1b83 100644 --- a/js/src/ui/SectionList/Overlay/overlay.js +++ b/js/src/ui/SectionList/Overlay/overlay.js @@ -16,7 +16,7 @@ import React from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './overlay.css'; diff --git a/js/src/ui/SectionList/sectionList.js b/js/src/ui/SectionList/sectionList.js index 8bd0b9a73..a9f6ea3ec 100644 --- a/js/src/ui/SectionList/sectionList.js +++ b/js/src/ui/SectionList/sectionList.js @@ -16,7 +16,7 @@ import React, { Component, PropTypes } from 'react'; -import { arrayOrObjectProptype, nodeOrStringProptype } from '~/util/proptypes'; +import { arrayOrObjectProptype, nodeOrStringProptype } from '@parity/shared/util/proptypes'; import { chunkArray } from './array'; import Overlay from './Overlay'; diff --git a/js/src/ui/SelectionList/selectionList.js b/js/src/ui/SelectionList/selectionList.js index 266dce893..b63e6f0b0 100644 --- a/js/src/ui/SelectionList/selectionList.js +++ b/js/src/ui/SelectionList/selectionList.js @@ -17,9 +17,10 @@ import { noop } from 'lodash'; import React, { Component, PropTypes } from 'react'; +import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; + import { StarIcon } from '~/ui/Icons'; import SectionList from '~/ui/SectionList'; -import { arrayOrObjectProptype } from '~/util/proptypes'; import styles from './selectionList.css'; diff --git a/js/src/ui/Tags/tags.js b/js/src/ui/Tags/tags.js index 503867dd6..30f2c434f 100644 --- a/js/src/ui/Tags/tags.js +++ b/js/src/ui/Tags/tags.js @@ -16,7 +16,7 @@ import React, { Component, PropTypes } from 'react'; -import { arrayOrObjectProptype } from '~/util/proptypes'; +import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; import styles from './tags.css'; diff --git a/js/src/ui/Title/Steps/steps.spec.js b/js/src/ui/Title/Steps/steps.spec.js new file mode 100644 index 000000000..5e4815d85 --- /dev/null +++ b/js/src/ui/Title/Steps/steps.spec.js @@ -0,0 +1,42 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { shallow } from 'enzyme'; +import React from 'react'; + +import Steps from './'; + +let component; + +function render (props = {}) { + component = shallow( + + ); + + return component; +} + +describe('ui/Title/Steps', () => { + beforeEach(() => { + render({ steps: ['stepA', 'stepB'] }); + }); + + it('renders the Stepper', () => { + expect(component.find('Stepper').get(0)).to.be.ok; + }); +}); diff --git a/js/src/ui/Title/Waiting/waiting.spec.js b/js/src/ui/Title/Waiting/waiting.spec.js new file mode 100644 index 000000000..73564f3f7 --- /dev/null +++ b/js/src/ui/Title/Waiting/waiting.spec.js @@ -0,0 +1,42 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { shallow } from 'enzyme'; +import React from 'react'; + +import Waiting from './'; + +let component; + +function render (props = {}) { + component = shallow( + + ); + + return component; +} + +describe('ui/Title/Waiting', () => { + beforeEach(() => { + render({ busy: true }); + }); + + it('renders the Progress', () => { + expect(component.find('Progress').get(0)).to.be.ok; + }); +}); diff --git a/js/src/ui/Title/title.js b/js/src/ui/Title/title.js index 49e607c34..410e5a060 100644 --- a/js/src/ui/Title/title.js +++ b/js/src/ui/Title/title.js @@ -16,8 +16,9 @@ import React, { PropTypes } from 'react'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; + import { Title as ContainerTitle } from '~/ui/Container'; -import { nodeOrStringProptype } from '~/util/proptypes'; import Steps from './Steps'; import Waiting from './Waiting'; diff --git a/js/src/ui/Title/title.spec.js b/js/src/ui/Title/title.spec.js index d193fde49..34affbf46 100644 --- a/js/src/ui/Title/title.spec.js +++ b/js/src/ui/Title/title.spec.js @@ -20,7 +20,6 @@ import React from 'react'; import Title from './'; let component; -let instance; function render (props = {}) { component = shallow( @@ -33,7 +32,6 @@ function render (props = {}) { { ...props } /> ); - instance = component.instance(); return component; } @@ -46,45 +44,4 @@ describe('ui/Title', () => { it('renders defaults', () => { expect(component).to.be.ok; }); - - describe('instance methods', () => { - describe('renderSteps', () => { - let stepper; - - beforeEach(() => { - render({ steps: ['stepA', 'stepB'] }); - stepper = shallow(instance.renderSteps()); - }); - - it('renders the Stepper', () => { - expect(stepper.find('Stepper').get(0)).to.be.ok; - }); - }); - - describe('renderTimeline', () => { - let steps; - - beforeEach(() => { - render({ steps: ['stepA', 'StepB'] }); - steps = instance.renderTimeline(); - }); - - it('renders the Step', () => { - expect(steps.length).to.equal(2); - }); - }); - - describe('renderWaiting', () => { - let waiting; - - beforeEach(() => { - render({ busy: true }); - waiting = shallow(instance.renderWaiting()); - }); - - it('renders the Progress', () => { - expect(waiting.find('Progress').get(0)).to.be.ok; - }); - }); - }); }); diff --git a/js/src/ui/TxHash/txHash.js b/js/src/ui/TxHash/txHash.js index 9ffa9166c..619be7de1 100644 --- a/js/src/ui/TxHash/txHash.js +++ b/js/src/ui/TxHash/txHash.js @@ -19,10 +19,10 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; +import { DEFAULT_GAS } from '@parity/shared/util/constants'; + import { txLink } from '~/3rdparty/etherscan/links'; import Warning from '~/ui/Warning'; -import { DEFAULT_GAS } from '~/util/constants'; - import Progress from '~/ui/Progress'; import ShortenedHash from '~/ui/ShortenedHash'; diff --git a/js/src/ui/TxList/TxRow/txRow.spec.js b/js/src/ui/TxList/TxRow/txRow.spec.js index a265f8d3a..dbe4f5dea 100644 --- a/js/src/ui/TxList/TxRow/txRow.spec.js +++ b/js/src/ui/TxList/TxRow/txRow.spec.js @@ -90,7 +90,7 @@ describe('ui/TxList/TxRow', () => { const element = render({ address: '0x123', block, netVersion: '42', tx }); - expect(element.find('Link').get(1).props.to).to.equal('/accounts/0x123'); + expect(element.find('DappLink').get(1).props.to).to.equal('/account/0x123'); }); it('renders address links', () => { @@ -107,7 +107,7 @@ describe('ui/TxList/TxRow', () => { const element = render({ address: '0x123', block, netVersion: '42', tx }); - expect(element.find('Link').get(1).props.to).to.equal('/addresses/0x456'); + expect(element.find('DappLink').get(1).props.to).to.equal('/address/0x456'); }); it('renders contract links', () => { @@ -124,7 +124,7 @@ describe('ui/TxList/TxRow', () => { const element = render({ address: '0x123', block, netVersion: '42', tx }); - expect(element.find('Link').get(1).props.to).to.equal('/contracts/0x999'); + expect(element.find('DappLink').get(1).props.to).to.equal('/contract/0x999'); }); }); }); diff --git a/js/src/ui/VaultCard/Accounts/accounts.spec.js b/js/src/ui/VaultCard/Accounts/accounts.spec.js new file mode 100644 index 000000000..db69f2a48 --- /dev/null +++ b/js/src/ui/VaultCard/Accounts/accounts.spec.js @@ -0,0 +1,62 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { shallow } from 'enzyme'; +import React from 'react'; + +import Accounts from './'; + +let component; + +function render (props = {}) { + component = shallow( + + ); + + return component; +} + +describe('ui/VaultCard/Accounts', () => { + beforeEach(() => { + render(); + }); + + it('renders empty when no accounts supplied', () => { + expect( + component.find('FormattedMessage').props().id + ).to.equal('vaults.accounts.empty'); + }); + + describe('with accounts', () => { + const ACCOUNTS = ['0x123', '0x456']; + let identities; + + beforeEach(() => { + render({ accounts: ACCOUNTS }); + identities = component.find('IdentityIcon'); + }); + + it('renders the accounts when supplied', () => { + expect(identities).to.have.length(2); + }); + + it('renders accounts with correct address', () => { + expect(identities.get(0).props.address).to.equal(ACCOUNTS[0]); + }); + }); +}); diff --git a/js/src/ui/VaultCard/Layout/layout.spec.js b/js/src/ui/VaultCard/Layout/layout.spec.js index f097f7a9b..d9f62a962 100644 --- a/js/src/ui/VaultCard/Layout/layout.spec.js +++ b/js/src/ui/VaultCard/Layout/layout.spec.js @@ -55,7 +55,7 @@ describe('ui/VaultCard/Layout', () => { let icon; beforeEach(() => { - icon = component.find('Connect(IdentityIcon)'); + icon = component.find('IdentityIcon'); }); it('renders', () => { diff --git a/js/src/ui/VaultCard/vaultCard.spec.js b/js/src/ui/VaultCard/vaultCard.spec.js index 2052aa707..6e15626f9 100644 --- a/js/src/ui/VaultCard/vaultCard.spec.js +++ b/js/src/ui/VaultCard/vaultCard.spec.js @@ -22,7 +22,6 @@ import VaultCard from './'; const VAULT = { name: 'testing', isOpen: true }; let component; -let instance; function render (props = {}) { component = shallow( @@ -31,7 +30,6 @@ function render (props = {}) { { ...props } /> ); - instance = component.instance(); return component; } @@ -62,33 +60,4 @@ describe('ui/VaultCard', () => { }); }); }); - - describe('instance methods', () => { - describe('renderAccounts', () => { - it('renders empty when no accounts supplied', () => { - expect( - shallow(instance.renderAccounts()).find('FormattedMessage').props().id - ).to.equal('vaults.accounts.empty'); - }); - - describe('with accounts', () => { - const ACCOUNTS = ['0x123', '0x456']; - let identities; - - beforeEach(() => { - render({ accounts: ACCOUNTS }); - identities = shallow(instance.renderAccounts()).find('Connect(IdentityIcon)'); - }); - - it('renders the accounts when supplied', () => { - expect(identities).to.have.length(2); - }); - - it('renders accounts with correct address', () => { - console.log(identities.get(0)); - expect(identities.get(0).props.address).to.equal(ACCOUNTS[0]); - }); - }); - }); - }); }); diff --git a/js/src/ui/Warning/warning.js b/js/src/ui/Warning/warning.js index f849489d8..602f77ca4 100644 --- a/js/src/ui/Warning/warning.js +++ b/js/src/ui/Warning/warning.js @@ -16,7 +16,7 @@ import React from 'react'; -import { nodeOrStringProptype } from '~/util/proptypes'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import styles from './warning.css'; diff --git a/js/src/views/Account/DeleteAccount/deleteAccount.js b/js/src/views/Account/DeleteAccount/deleteAccount.js index cd69d6bd9..e3d9b95f9 100644 --- a/js/src/views/Account/DeleteAccount/deleteAccount.js +++ b/js/src/views/Account/DeleteAccount/deleteAccount.js @@ -19,8 +19,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { newError } from '@parity/shared/redux/actions'; + import { ConfirmDialog, IdentityIcon, IdentityName, Input } from '~/ui'; -import { newError } from '~/redux/actions'; import styles from './deleteAccount.css'; diff --git a/js/src/views/Account/EditMeta/editMeta.js b/js/src/views/Account/EditMeta/editMeta.js index 5d0c91dbe..0bc24f104 100644 --- a/js/src/views/Account/EditMeta/editMeta.js +++ b/js/src/views/Account/EditMeta/editMeta.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { Button, Form, Input, InputChip, Portal, VaultSelect } from '~/ui'; import { CancelIcon, SaveIcon } from '~/ui/Icons'; import VaultStore from '~/views/Vaults/store'; diff --git a/js/src/views/Account/EditMeta/store.js b/js/src/views/Account/EditMeta/store.js index da3d88cd7..55e1d3633 100644 --- a/js/src/views/Account/EditMeta/store.js +++ b/js/src/views/Account/EditMeta/store.js @@ -16,7 +16,7 @@ import { action, computed, observable, transaction } from 'mobx'; -import { validateName } from '~/util/validation'; +import { validateName } from '@parity/shared/util/validation'; export default class Store { @observable address = null; diff --git a/js/src/views/Account/Header/header.spec.js b/js/src/views/Account/Header/header.spec.js index 48c0b1a99..d761807b4 100644 --- a/js/src/views/Account/Header/header.spec.js +++ b/js/src/views/Account/Header/header.spec.js @@ -18,7 +18,7 @@ import BigNumber from 'bignumber.js'; import { shallow } from 'enzyme'; import React from 'react'; -import { ETH_TOKEN } from '~/util/tokens'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; import Header from './'; @@ -137,7 +137,7 @@ describe('views/Account/Header', () => { beforeEach(() => { render(); - icon = component.find('Connect(IdentityIcon)'); + icon = component.find('IdentityIcon'); }); it('renders', () => { diff --git a/js/src/views/Account/PasswordManager/passwordManager.js b/js/src/views/Account/PasswordManager/passwordManager.js index ce770afbf..3201f57e0 100644 --- a/js/src/views/Account/PasswordManager/passwordManager.js +++ b/js/src/views/Account/PasswordManager/passwordManager.js @@ -22,7 +22,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError, openSnackbar } from '~/redux/actions'; +import { newError, openSnackbar } from '@parity/shared/redux/actions'; + import { Button, IdentityName, IdentityIcon, Portal } from '~/ui'; import PasswordStrength from '~/ui/Form/PasswordStrength'; import Form, { Input } from '~/ui/Form'; diff --git a/js/src/views/Account/Transfer/Details/details.js b/js/src/views/Account/Transfer/Details/details.js index ecc102718..2bbf6d4a7 100644 --- a/js/src/views/Account/Transfer/Details/details.js +++ b/js/src/views/Account/Transfer/Details/details.js @@ -17,8 +17,9 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import Form, { Input, InputAddressSelect, AddressSelect, Checkbox } from '~/ui/Form'; -import { nullableProptype } from '~/util/proptypes'; import TokenSelect from './tokenSelect'; import styles from '../transfer.css'; diff --git a/js/src/views/Account/Transfer/store.js b/js/src/views/Account/Transfer/store.js index 509895223..66fddf1d6 100644 --- a/js/src/views/Account/Transfer/store.js +++ b/js/src/views/Account/Transfer/store.js @@ -20,13 +20,13 @@ import BigNumber from 'bignumber.js'; import Contract from '@parity/api/contract'; import { fromWei } from '@parity/api/util/wei'; +import { getLogger, LOG_KEYS } from '@parity/shared/config'; +import { eip20 as tokenAbi, wallet as walletAbi } from '@parity/shared/contracts/abi'; +import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '@parity/shared/util/constants'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; -import { eip20 as tokenAbi, wallet as walletAbi } from '~/contracts/abi'; import ERRORS from './errors'; -import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '~/util/constants'; -import { ETH_TOKEN } from '~/util/tokens'; import GasPriceStore from '~/ui/GasPriceEditor/store'; -import { getLogger, LOG_KEYS } from '~/config'; const log = getLogger(LOG_KEYS.TransferModalStore); diff --git a/js/src/views/Account/Transfer/transfer.js b/js/src/views/Account/Transfer/transfer.js index ab769ff02..c4c3de74d 100644 --- a/js/src/views/Account/Transfer/transfer.js +++ b/js/src/views/Account/Transfer/transfer.js @@ -21,10 +21,11 @@ import { bindActionCreators } from 'redux'; import { observer } from 'mobx-react'; import { pick } from 'lodash'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { Button, IdentityIcon, Portal, Warning } from '~/ui'; import { newError } from '~/ui/Errors/actions'; import { CancelIcon, NextIcon, PrevIcon } from '~/ui/Icons'; -import { nullableProptype } from '~/util/proptypes'; import Details from './Details'; import Extras from './Extras'; diff --git a/js/src/views/Account/Verification/GatherData/gatherData.js b/js/src/views/Account/Verification/GatherData/gatherData.js index 12369359f..c72c706e0 100644 --- a/js/src/views/Account/Verification/GatherData/gatherData.js +++ b/js/src/views/Account/Verification/GatherData/gatherData.js @@ -22,7 +22,7 @@ import { fromWei } from '@parity/api/util/wei'; import { Checkbox, Form, Input } from '~/ui'; import { DoneIcon, ErrorIcon, InfoIcon } from '~/ui/Icons'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; import smsTermsOfService from '~/3rdparty/sms-verification/terms-of-service'; import emailTermsOfService from '~/3rdparty/email-verification/terms-of-service'; diff --git a/js/src/views/Account/Verification/QueryCode/queryCode.js b/js/src/views/Account/Verification/QueryCode/queryCode.js index 608e92f3f..b57dc4c1e 100644 --- a/js/src/views/Account/Verification/QueryCode/queryCode.js +++ b/js/src/views/Account/Verification/QueryCode/queryCode.js @@ -17,8 +17,9 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; + import { Form, Input } from '~/ui'; -import { nodeOrStringProptype } from '~/util/proptypes'; export default class QueryCode extends Component { static propTypes = { diff --git a/js/src/views/Account/Verification/SendConfirmation/sendConfirmation.js b/js/src/views/Account/Verification/SendConfirmation/sendConfirmation.js index bcff62591..bfa8fe3ea 100644 --- a/js/src/views/Account/Verification/SendConfirmation/sendConfirmation.js +++ b/js/src/views/Account/Verification/SendConfirmation/sendConfirmation.js @@ -17,7 +17,8 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import TxHash from '~/ui/TxHash'; import { POSTING_CONFIRMATION, POSTED_CONFIRMATION diff --git a/js/src/views/Account/Verification/SendRequest/sendRequest.js b/js/src/views/Account/Verification/SendRequest/sendRequest.js index 7df4ef1e4..417ce982c 100644 --- a/js/src/views/Account/Verification/SendRequest/sendRequest.js +++ b/js/src/views/Account/Verification/SendRequest/sendRequest.js @@ -17,7 +17,8 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { nullableProptype } from '~/util/proptypes'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import TxHash from '~/ui/TxHash'; import { POSTING_REQUEST, POSTED_REQUEST, REQUESTING_CODE diff --git a/js/src/views/Account/Verification/email-store.js b/js/src/views/Account/Verification/email-store.js index b5a996a8b..e299b70f8 100644 --- a/js/src/views/Account/Verification/email-store.js +++ b/js/src/views/Account/Verification/email-store.js @@ -18,8 +18,8 @@ import { observable, computed, action } from 'mobx'; import { bytesToHex } from '@parity/api/util/format'; import { sha3 } from '@parity/api/util/sha3'; +import EmailVerificationABI from '@parity/shared/contracts/abi/email-verification.json'; -import EmailVerificationABI from '~/contracts/abi/email-verification.json'; import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; diff --git a/js/src/views/Account/Verification/sms-store.js b/js/src/views/Account/Verification/sms-store.js index 25c07403c..fa48fea62 100644 --- a/js/src/views/Account/Verification/sms-store.js +++ b/js/src/views/Account/Verification/sms-store.js @@ -17,10 +17,9 @@ import { observable, computed, action } from 'mobx'; import phone from 'phoneformat.js'; -import SMSVerificationABI from '~/contracts/abi/sms-verification.json'; -import VerificationStore, { - LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE -} from './store'; +import SMSVerificationABI from '@parity/shared/contracts/abi/sms-verification.json'; + +import VerificationStore, { LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE } from './store'; import { isServerRunning, hasReceivedCode, postToServer } from '~/3rdparty/sms-verification'; // name in the `BadgeReg.sol` contract diff --git a/js/src/views/Account/Verification/store.js b/js/src/views/Account/Verification/store.js index b3c375dcc..50bcbe2c0 100644 --- a/js/src/views/Account/Verification/store.js +++ b/js/src/views/Account/Verification/store.js @@ -18,10 +18,9 @@ import { observable, autorun, action } from 'mobx'; import Contract from '@parity/api/contract'; import { sha3 } from '@parity/api/util/sha3'; - -import Contracts from '~/contracts'; -import { checkIfVerified, findLastRequested, awaitPuzzle } from '~/contracts/verification'; -import { checkIfTxFailed, waitForConfirmations } from '~/util/tx'; +import Contracts from '@parity/shared/contracts'; +import { checkIfVerified, findLastRequested, awaitPuzzle } from '@parity/shared/contracts/verification'; +import { checkIfTxFailed, waitForConfirmations } from '@parity/shared/util/tx'; export const LOADING = 'fetching-contract'; export const QUERY_DATA = 'query-data'; diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index 18139928f..c7417e041 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -20,13 +20,13 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import shapeshiftBtn from '~/../assets/images/shapeshift-btn.png'; +import HardwareStore from '@parity/shared/mobx/hardwareStore'; +import HistoryStore from '@parity/shared/mobx/historyStore'; +import { newError } from '@parity/shared/redux/actions'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; +import { fetchCertifiers, fetchCertifications } from '@parity/shared/redux/providers/certifications/actions'; -import { newError } from '~/redux/actions'; -import HardwareStore from '~/mobx/hardwareStore'; -import HistoryStore from '~/mobx/historyStore'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; -import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions'; +import shapeshiftBtn from '~/../assets/images/shapeshift-btn.png'; import { Actionbar, Button, ConfirmDialog, Input, Page, Portal } from '~/ui'; import { DeleteIcon, DialIcon, EditIcon, LockedIcon, SendIcon, VerifyIcon, FileDownloadIcon } from '~/ui/Icons'; diff --git a/js/src/views/Account/account.spec.js b/js/src/views/Account/account.spec.js index 6a96d6300..54720889c 100644 --- a/js/src/views/Account/account.spec.js +++ b/js/src/views/Account/account.spec.js @@ -19,7 +19,7 @@ import React from 'react'; import { ACCOUNTS, ADDRESS, createRedux } from './account.test.js'; -import Account from './'; +import Account from './account'; let component; let instance; diff --git a/js/src/views/Account/index.js b/js/src/views/Account/index.js index 868cd429f..1227884cd 100644 --- a/js/src/views/Account/index.js +++ b/js/src/views/Account/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Accounts/CreateAccount/GethCard/gethCard.js b/js/src/views/Accounts/CreateAccount/GethCard/gethCard.js index fb95b7515..c084cb4f5 100644 --- a/js/src/views/Accounts/CreateAccount/GethCard/gethCard.js +++ b/js/src/views/Accounts/CreateAccount/GethCard/gethCard.js @@ -16,8 +16,9 @@ import React, { Component, PropTypes } from 'react'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; + import { AccountCard } from '~/ui'; -import { ETH_TOKEN } from '~/util/tokens'; export default class GethCard extends Component { static propTypes = { diff --git a/js/src/views/Accounts/CreateAccount/createAccount.js b/js/src/views/Accounts/CreateAccount/createAccount.js index 1fdc66003..4fcf4d8fe 100644 --- a/js/src/views/Accounts/CreateAccount/createAccount.js +++ b/js/src/views/Accounts/CreateAccount/createAccount.js @@ -21,9 +21,9 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { createIdentityImg } from '@parity/api/util/identity'; +import { newError } from '@parity/shared/redux/actions'; import ParityLogo from '~/../assets/images/parity-logo-black-no-text.svg'; -import { newError } from '~/redux/actions'; import { Button, ModalBox, Portal } from '~/ui'; import { CancelIcon, CheckIcon, DoneIcon, NextIcon, PrevIcon, PrintIcon } from '~/ui/Icons'; diff --git a/js/src/views/Accounts/CreateWallet/WalletType/walletType.js b/js/src/views/Accounts/CreateWallet/WalletType/walletType.js index bbf55965b..baf1d19b7 100644 --- a/js/src/views/Accounts/CreateWallet/WalletType/walletType.js +++ b/js/src/views/Accounts/CreateWallet/WalletType/walletType.js @@ -17,7 +17,8 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { walletSourceURL } from '~/contracts/code/wallet'; +import { walletSourceURL } from '@parity/shared/contracts/code/wallet'; + import { RadioButtons } from '~/ui'; const TYPES = [ diff --git a/js/src/views/Accounts/CreateWallet/createWallet.js b/js/src/views/Accounts/CreateWallet/createWallet.js index 63be12d34..b0d57efbe 100644 --- a/js/src/views/Accounts/CreateWallet/createWallet.js +++ b/js/src/views/Accounts/CreateWallet/createWallet.js @@ -20,9 +20,10 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { setRequest } from '@parity/shared/redux/providers/requestsActions'; + import { Button, Portal } from '~/ui'; import { CancelIcon, DoneIcon, NextIcon } from '~/ui/Icons'; -import { setRequest } from '~/redux/providers/requestsActions'; import WalletType from './WalletType'; import WalletDetails from './WalletDetails'; diff --git a/js/src/views/Accounts/CreateWallet/createWalletStore.js b/js/src/views/Accounts/CreateWallet/createWalletStore.js index c4526e582..0411aeeac 100644 --- a/js/src/views/Accounts/CreateWallet/createWalletStore.js +++ b/js/src/views/Accounts/CreateWallet/createWalletStore.js @@ -21,14 +21,12 @@ import { FormattedMessage } from 'react-intl'; import Contract from '@parity/api/contract'; import { toWei } from '@parity/api/util/wei'; - -import Contracts from '~/contracts'; -import { wallet as walletAbi } from '~/contracts/abi'; -import { wallet as walletCode, walletLibrary as walletLibraryCode, walletLibraryRegKey, fullWalletCode } from '~/contracts/code/wallet'; - -import { validateUint, validateAddress, validateName } from '~/util/validation'; -import { deploy } from '~/util/tx'; -import WalletsUtils from '~/util/wallets'; +import Contracts from '@parity/shared/contracts'; +import { wallet as walletAbi } from '@parity/shared/contracts/abi'; +import { wallet as walletCode, walletLibrary as walletLibraryCode, walletLibraryRegKey, fullWalletCode } from '@parity/shared/contracts/code/wallet'; +import { validateUint, validateAddress, validateName } from '@parity/shared/util/validation'; +import { deploy } from '@parity/shared/util/tx'; +import WalletsUtils from '@parity/shared/util/wallets'; const STEPS = { TYPE: { diff --git a/js/src/views/Accounts/ExportAccount/exportAccount.js b/js/src/views/Accounts/ExportAccount/exportAccount.js index 48faaaec3..e0f97c292 100644 --- a/js/src/views/Accounts/ExportAccount/exportAccount.js +++ b/js/src/views/Accounts/ExportAccount/exportAccount.js @@ -20,8 +20,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; -import { personalAccountsInfo } from '~/redux/providers/personalActions'; +import { newError } from '@parity/shared/redux/actions'; +import { personalAccountsInfo } from '@parity/shared/redux/providers/personalActions'; + import { AccountCard, Button, Portal, SelectionList } from '~/ui'; import { CancelIcon, CheckIcon } from '~/ui/Icons'; import ExportInput from './exportInput'; diff --git a/js/src/views/Accounts/List/list.js b/js/src/views/Accounts/List/list.js index 2fa3be70b..7fa0e6c8a 100644 --- a/js/src/views/Accounts/List/list.js +++ b/js/src/views/Accounts/List/list.js @@ -19,9 +19,10 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { ETH_TOKEN } from '@parity/shared/util/tokens'; +import { fetchCertifiers, fetchCertifications } from '@parity/shared/redux/providers/certifications/actions'; + import { Container, SectionList } from '~/ui'; -import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions'; -import { ETH_TOKEN } from '~/util/tokens'; import Summary from '../Summary'; import styles from './list.css'; diff --git a/js/src/views/Accounts/Summary/summary.js b/js/src/views/Accounts/Summary/summary.js index 3e0ab7eab..4e378bc4d 100644 --- a/js/src/views/Accounts/Summary/summary.js +++ b/js/src/views/Accounts/Summary/summary.js @@ -22,9 +22,10 @@ import { isEqual } from 'lodash'; import ReactTooltip from 'react-tooltip'; import { FormattedMessage } from 'react-intl'; +import { arrayOrObjectProptype, nullableProptype } from '@parity/shared/util/proptypes'; + import { Balance, Container, ContainerTitle, CopyToClipboard, IdentityIcon, IdentityName, Tags, VaultTag } from '~/ui'; import Certifications from '~/ui/Certifications'; -import { arrayOrObjectProptype, nullableProptype } from '~/util/proptypes'; import styles from '../accounts.css'; diff --git a/js/src/views/Accounts/accounts.js b/js/src/views/Accounts/accounts.js index cfafb05d6..35d7338c6 100644 --- a/js/src/views/Accounts/accounts.js +++ b/js/src/views/Accounts/accounts.js @@ -22,10 +22,11 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import HardwareStore from '~/mobx/hardwareStore'; +import HardwareStore from '@parity/shared/mobx/hardwareStore'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; + import { Actionbar, ActionbarSearch, ActionbarSort, Button, Page } from '~/ui'; import { AddIcon, FileDownloadIcon } from '~/ui/Icons'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; import CreateWallet from './CreateWallet'; import CreateAccount from './CreateAccount'; diff --git a/js/src/views/Accounts/accounts.spec.js b/js/src/views/Accounts/accounts.spec.js index 7bd798105..6b1a0bfa5 100644 --- a/js/src/views/Accounts/accounts.spec.js +++ b/js/src/views/Accounts/accounts.spec.js @@ -18,7 +18,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import sinon from 'sinon'; -import Accounts from './'; +import Accounts from './accounts'; let api; let component; diff --git a/js/src/views/Accounts/index.js b/js/src/views/Accounts/index.js index 7265ff545..d092a9150 100644 --- a/js/src/views/Accounts/index.js +++ b/js/src/views/Accounts/index.js @@ -21,13 +21,14 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); -import { api } from './parity'; +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; +import { api } from './parity'; + import Accounts from './accounts'; ContractInstances.get(api); diff --git a/js/src/views/Address/Delete/delete.js b/js/src/views/Address/Delete/delete.js index cf0380f2f..ea36bf903 100644 --- a/js/src/views/Address/Delete/delete.js +++ b/js/src/views/Address/Delete/delete.js @@ -19,8 +19,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { newError } from '@parity/shared/redux/actions'; + import { ConfirmDialog, IdentityIcon, IdentityName } from '~/ui'; -import { newError } from '~/redux/actions'; import styles from '../address.css'; diff --git a/js/src/views/Address/address.js b/js/src/views/Address/address.js index 340232c50..26323173f 100644 --- a/js/src/views/Address/address.js +++ b/js/src/views/Address/address.js @@ -19,6 +19,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; + import { Actionbar, Button, Page } from '~/ui'; import { AddIcon, DeleteIcon, EditIcon } from '~/ui/Icons'; @@ -27,7 +29,6 @@ import Header from '../Account/Header'; import Transactions from '../Account/Transactions'; import AddAddress from '../Addresses/AddAddress'; import Delete from './Delete'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; class Address extends Component { static contextTypes = { diff --git a/js/src/views/Address/index.js b/js/src/views/Address/index.js index e39616f69..2469b7b3c 100644 --- a/js/src/views/Address/index.js +++ b/js/src/views/Address/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Addresses/AddAddress/store.js b/js/src/views/Addresses/AddAddress/store.js index 3980e2f7f..b7397b3d6 100644 --- a/js/src/views/Addresses/AddAddress/store.js +++ b/js/src/views/Addresses/AddAddress/store.js @@ -16,7 +16,7 @@ import { action, computed, transaction, observable } from 'mobx'; -import { ERRORS, validateAddress, validateName } from '~/util/validation'; +import { ERRORS, validateAddress, validateName } from '@parity/shared/util/validation'; export default class Store { @observable address = ''; diff --git a/js/src/views/Addresses/addresses.js b/js/src/views/Addresses/addresses.js index 2f163eeb9..e7e3c9454 100644 --- a/js/src/views/Addresses/addresses.js +++ b/js/src/views/Addresses/addresses.js @@ -20,9 +20,10 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { uniq, isEqual } from 'lodash'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; + import { Actionbar, ActionbarExport, ActionbarImport, ActionbarSearch, ActionbarSort, Button, Page } from '~/ui'; import { AddIcon } from '~/ui/Icons'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; import List from '../Accounts/List'; import Summary from '../Accounts/Summary'; diff --git a/js/src/views/Addresses/index.js b/js/src/views/Addresses/index.js index 4a6f04010..67adc21ae 100644 --- a/js/src/views/Addresses/index.js +++ b/js/src/views/Addresses/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Contract/Events/Event/event.js b/js/src/views/Contract/Events/Event/event.js index eb370e7f1..fc2436f8e 100644 --- a/js/src/views/Contract/Events/Event/event.js +++ b/js/src/views/Contract/Events/Event/event.js @@ -112,11 +112,16 @@ export default class Event extends Component { } renderParam (name, param) { + // Don't add a label id the name is an index key (ie. a Number) + const label = parseInt(name).toString() === name.toString() + ? undefined + : name; + return ( = 0) { + api.unsubscribe(blockSubscriptionId); + } + + if (subscriptionId >= 0) { + contract.unsubscribe(subscriptionId); + } + this.props.setVisibleAccounts([]); } diff --git a/js/src/views/Contract/index.js b/js/src/views/Contract/index.js index 58284171c..9424be64f 100644 --- a/js/src/views/Contract/index.js +++ b/js/src/views/Contract/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/ContractDevelop/SaveContract/saveContract.js b/js/src/views/ContractDevelop/SaveContract/saveContract.js index 7f45b6aa5..cb94a087e 100644 --- a/js/src/views/ContractDevelop/SaveContract/saveContract.js +++ b/js/src/views/ContractDevelop/SaveContract/saveContract.js @@ -17,10 +17,11 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { ERRORS, validateName } from '@parity/shared/util/validation'; + import { Button, Form, Input, Portal } from '~/ui'; import Editor from '~/ui/Editor'; import { CancelIcon, SaveIcon } from '~/ui/Icons'; -import { ERRORS, validateName } from '~/util/validation'; import styles from './saveContract.css'; diff --git a/js/src/views/ContractDevelop/contractDevelop.js b/js/src/views/ContractDevelop/contractDevelop.js index c5410b39b..1af924f0e 100644 --- a/js/src/views/ContractDevelop/contractDevelop.js +++ b/js/src/views/ContractDevelop/contractDevelop.js @@ -273,24 +273,6 @@ class ContractDevelop extends Component { renderParameters () { const { compiling, contract, selectedBuild, loading, workerError } = this.store; - if (workerError) { - return ( -
-
-

- -

-
- { workerError.toString() } -
-
-
- ); - } - if (selectedBuild < 0) { return (
@@ -308,10 +290,28 @@ class ContractDevelop extends Component { ); } - if (loading) { + let content; + + if (workerError) { + content = ( +
+
+

+ +

+
+ { workerError.toString() } +
+
+
+ ); + } else if (loading) { const { longVersion } = this.store.builds[selectedBuild]; - return ( + content = (
); + } else { + content = this.renderCompilation(); } return ( @@ -394,7 +396,7 @@ class ContractDevelop extends Component {
{ this.renderSolidityVersions() } - { this.renderCompilation() } + { content }
); } diff --git a/js/src/views/ContractDevelop/index.js b/js/src/views/ContractDevelop/index.js index d0fb67a9f..5dc0aaa10 100644 --- a/js/src/views/ContractDevelop/index.js +++ b/js/src/views/ContractDevelop/index.js @@ -21,9 +21,10 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/ContractDevelop/store.js b/js/src/views/ContractDevelop/store.js index cf2154548..9c799a648 100644 --- a/js/src/views/ContractDevelop/store.js +++ b/js/src/views/ContractDevelop/store.js @@ -21,10 +21,9 @@ import { FormattedMessage } from 'react-intl'; import store from 'store'; import { sha3 } from '@parity/api/util/sha3'; +import SolidityUtils from '@parity/shared/util/solidity'; -import SolidityUtils from '~/util/solidity'; - -const SOLIDITY_LIST_URL = 'https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/list.json'; +const SOLIDITY_LIST_URL = 'https://rawgit.com/ethereum/solc-bin/gh-pages/bin/list.json'; const WRITE_CONTRACT_STORE_KEY = '_parity::contractDevelop'; const SNIPPETS = { @@ -37,7 +36,7 @@ const SNIPPETS = { /> ), id: 'snippet0', - sourcecode: require('raw-loader!../../contracts/snippets/token.sol') + sourcecode: require('raw-loader!@parity/shared/contracts/snippets/token.sol') }, snippet1: { name: 'StandardToken.sol', @@ -48,7 +47,7 @@ const SNIPPETS = { /> ), id: 'snippet1', - sourcecode: require('raw-loader!../../contracts/snippets/standard-token.sol') + sourcecode: require('raw-loader!@parity/shared/contracts/snippets/standard-token.sol') }, snippet2: { name: 'HumanStandardToken.sol', @@ -59,7 +58,7 @@ const SNIPPETS = { /> ), id: 'snippet2', - sourcecode: require('raw-loader!../../contracts/snippets/human-standard-token.sol') + sourcecode: require('raw-loader!@parity/shared/contracts/snippets/human-standard-token.sol') }, snippet3: { name: 'Wallet.sol', @@ -70,7 +69,7 @@ const SNIPPETS = { /> ), id: 'snippet3', - sourcecode: require('raw-loader!../../contracts/snippets/wallet.sol') + sourcecode: require('raw-loader!@parity/shared/contracts/snippets/wallet.sol') } }; @@ -140,9 +139,10 @@ export default class ContractDevelopStore { this.worker = worker; - this - .fetchSolidityVersions() - .then(() => this.reloadContracts()); + return Promise.all([ + this.fetchSolidityVersions(), + this.reloadContracts(undefined, undefined, false) + ]); } fetchSolidityVersions () { @@ -198,6 +198,7 @@ export default class ContractDevelopStore { }) .catch((error) => { this.setWorkerError(error); + throw error; }); } @@ -319,6 +320,7 @@ export default class ContractDevelopStore { transaction(() => { this.compiled = false; this.compiling = true; + this.setWorkerError(null); }); const build = this.builds[this.selectedBuild]; @@ -366,12 +368,16 @@ export default class ContractDevelopStore { annotations, contracts, errors } = data.result; - this.contract = contract; - this.contractIndex = contractIndex; + if (!contract && errors && errors.length > 0) { + this.setWorkerError(errors[0]); + } else { + this.contract = contract; + this.contractIndex = contractIndex; - this.annotations = annotations; - this.contracts = contracts; - this.errors = errors; + this.annotations = annotations; + this.contracts = contracts; + this.errors = errors; + } } this.compiled = true; @@ -392,11 +398,10 @@ export default class ContractDevelopStore { const { errors = [] } = data; const errorAnnotations = this.parseErrors(errors); - const formalAnnotations = this.parseErrors(data.formal && data.formal.errors, true); + // const formalAnnotations = this.parseErrors(data.formal && data.formal.errors, true); const annotations = [].concat( - errorAnnotations, - formalAnnotations + errorAnnotations ); const contractKeys = Object.keys(contracts || {}); @@ -488,7 +493,7 @@ export default class ContractDevelopStore { this.reloadContracts(cId); } - @action reloadContracts = (id, sourcecode) => { + @action reloadContracts = (id, sourcecode, recompile = true) => { const localStore = store.get(WRITE_CONTRACT_STORE_KEY) || {}; this.savedContracts = localStore.saved || {}; @@ -508,7 +513,9 @@ export default class ContractDevelopStore { this.resizeEditor(); - return this.handleCompile(); + if (recompile) { + return this.handleCompile(); + } } @action handleLoadContract = (contract) => { diff --git a/js/src/views/Contracts/AddContract/addContract.js b/js/src/views/Contracts/AddContract/addContract.js index f10515d1b..909f48dc2 100644 --- a/js/src/views/Contracts/AddContract/addContract.js +++ b/js/src/views/Contracts/AddContract/addContract.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { Button, Form, Input, InputAddress, Portal, RadioButtons } from '~/ui'; import { AddIcon, CancelIcon, NextIcon, PrevIcon } from '~/ui/Icons'; diff --git a/js/src/views/Contracts/AddContract/store.js b/js/src/views/Contracts/AddContract/store.js index 9d47e5f1d..61e04c616 100644 --- a/js/src/views/Contracts/AddContract/store.js +++ b/js/src/views/Contracts/AddContract/store.js @@ -16,7 +16,7 @@ import { action, computed, observable, transaction } from 'mobx'; -import { ERRORS, validateAbi, validateAddress, validateName } from '~/util/validation'; +import { ERRORS, validateAbi, validateAddress, validateName } from '@parity/shared/util/validation'; import { ABI_TYPES } from './types'; diff --git a/js/src/views/Contracts/AddContract/types.js b/js/src/views/Contracts/AddContract/types.js index b229fc7ac..d34a33783 100644 --- a/js/src/views/Contracts/AddContract/types.js +++ b/js/src/views/Contracts/AddContract/types.js @@ -17,7 +17,7 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; -import { eip20, wallet } from '~/contracts/abi'; +import { eip20, wallet } from '@parity/shared/contracts/abi'; const ABI_TYPES = [ { diff --git a/js/src/views/Contracts/DeployContract/DetailsStep/detailsStep.js b/js/src/views/Contracts/DeployContract/DetailsStep/detailsStep.js index 7f0976d5d..a7824e5ba 100644 --- a/js/src/views/Contracts/DeployContract/DetailsStep/detailsStep.js +++ b/js/src/views/Contracts/DeployContract/DetailsStep/detailsStep.js @@ -18,9 +18,10 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { MenuItem } from 'material-ui'; +import { parseAbiType } from '@parity/shared/util/abi'; +import { validateAbi } from '@parity/shared/util/validation'; + import { AddressSelect, Checkbox, Form, Input, Select } from '~/ui'; -import { validateAbi } from '~/util/validation'; -import { parseAbiType } from '~/util/abi'; const CHECK_STYLE = { marginTop: '1em' diff --git a/js/src/views/Contracts/DeployContract/ParametersStep/parametersStep.js b/js/src/views/Contracts/DeployContract/ParametersStep/parametersStep.js index 0213bfa01..fd15d291a 100644 --- a/js/src/views/Contracts/DeployContract/ParametersStep/parametersStep.js +++ b/js/src/views/Contracts/DeployContract/ParametersStep/parametersStep.js @@ -32,8 +32,9 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { parseAbiType } from '@parity/shared/util/abi'; + import { Form, TypedInput } from '~/ui'; -import { parseAbiType } from '~/util/abi'; import styles from '../deployContract.css'; diff --git a/js/src/views/Contracts/DeployContract/deployContract.js b/js/src/views/Contracts/DeployContract/deployContract.js index 55bbf2efa..068795f8e 100644 --- a/js/src/views/Contracts/DeployContract/deployContract.js +++ b/js/src/views/Contracts/DeployContract/deployContract.js @@ -21,11 +21,12 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { setRequest } from '@parity/shared/redux/providers/requestsActions'; +import { ERRORS, validateAbi, validateCode, validateName, validatePositiveNumber } from '@parity/shared/util/validation'; +import { deploy, deployEstimateGas } from '@parity/shared/util/tx'; + import { Button, GasPriceEditor, IdentityIcon, Portal, Warning } from '~/ui'; import { CancelIcon } from '~/ui/Icons'; -import { ERRORS, validateAbi, validateCode, validateName, validatePositiveNumber } from '~/util/validation'; -import { deploy, deployEstimateGas } from '~/util/tx'; -import { setRequest } from '~/redux/providers/requestsActions'; import DetailsStep from './DetailsStep'; import ParametersStep from './ParametersStep'; diff --git a/js/src/views/Contracts/contracts.js b/js/src/views/Contracts/contracts.js index 5185b0a2c..f2fb2c064 100644 --- a/js/src/views/Contracts/contracts.js +++ b/js/src/views/Contracts/contracts.js @@ -20,7 +20,8 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { uniq, isEqual } from 'lodash'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; + import { Actionbar, ActionbarSearch, ActionbarSort, Button, Page } from '~/ui'; import { AddIcon } from '~/ui/Icons'; diff --git a/js/src/views/Contracts/index.js b/js/src/views/Contracts/index.js index d59d3d1b0..0f73414c9 100644 --- a/js/src/views/Contracts/index.js +++ b/js/src/views/Contracts/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Home/Accounts/accounts.js b/js/src/views/Home/Accounts/accounts.js index f397994ff..42dcaf39c 100644 --- a/js/src/views/Home/Accounts/accounts.js +++ b/js/src/views/Home/Accounts/accounts.js @@ -20,8 +20,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { Link } from 'react-router'; +import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; + import { Container, ContainerTitle, IdentityName, IdentityIcon, SectionList } from '~/ui'; -import { arrayOrObjectProptype } from '~/util/proptypes'; import styles from './accounts.css'; diff --git a/js/src/views/Home/Dapps/dapps.js b/js/src/views/Home/Dapps/dapps.js index 608d4435b..307e9b440 100644 --- a/js/src/views/Home/Dapps/dapps.js +++ b/js/src/views/Home/Dapps/dapps.js @@ -17,8 +17,9 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { arrayOrObjectProptype } from '@parity/shared//util/proptypes'; + import { ContainerTitle, SectionList } from '~/ui'; -import { arrayOrObjectProptype } from '~/util/proptypes'; import Dapp from './dapp'; import styles from './dapps.css'; diff --git a/js/src/views/Home/News/news.test.js b/js/src/views/Home/News/news.test.js index 4b45502a7..c5d3dbcac 100644 --- a/js/src/views/Home/News/news.test.js +++ b/js/src/views/Home/News/news.test.js @@ -16,7 +16,7 @@ import sinon from 'sinon'; -import Contracts from '~/contracts'; +import Contracts from '@parity/shared/contracts'; import { VERSION_ID } from './news'; diff --git a/js/src/views/Home/News/store.js b/js/src/views/Home/News/store.js index cf46227ae..b6f04787c 100644 --- a/js/src/views/Home/News/store.js +++ b/js/src/views/Home/News/store.js @@ -15,7 +15,8 @@ // along with Parity. If not, see . import { action, observable } from 'mobx'; -import Contracts from '~/contracts'; + +import Contracts from '@parity/shared/contracts'; let instance = null; diff --git a/js/src/views/Home/Urls/urls.js b/js/src/views/Home/Urls/urls.js index 3b38be637..7ded1ecda 100644 --- a/js/src/views/Home/Urls/urls.js +++ b/js/src/views/Home/Urls/urls.js @@ -26,6 +26,10 @@ import styles from './urls.css'; @observer export default class Urls extends Component { + static contextTypes = { + router: PropTypes.object.isRequired + }; + static propTypes = { extensionStore: PropTypes.object.isRequired, store: PropTypes.object.isRequired diff --git a/js/src/views/Home/home.js b/js/src/views/Home/home.js index a9e8dfa00..5b01d31e8 100644 --- a/js/src/views/Home/home.js +++ b/js/src/views/Home/home.js @@ -18,7 +18,8 @@ import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import HistoryStore from '~/mobx/historyStore'; +import HistoryStore from '@parity/shared/mobx/historyStore'; + import { Page } from '~/ui'; import WebStore from '~/views/Web/store'; diff --git a/js/src/views/Home/home.spec.js b/js/src/views/Home/home.spec.js index 2fccccee1..cad89f2b2 100644 --- a/js/src/views/Home/home.spec.js +++ b/js/src/views/Home/home.spec.js @@ -18,7 +18,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import sinon from 'sinon'; -import Home from './'; +import Home from './home'; const TEST_APP_HISTORY = []; diff --git a/js/src/views/Home/index.js b/js/src/views/Home/index.js index 92e46e29c..ff381ab69 100644 --- a/js/src/views/Home/index.js +++ b/js/src/views/Home/index.js @@ -21,9 +21,10 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Playground/index.js b/js/src/views/Playground/index.js index 8ffef2ae6..5b36151ab 100644 --- a/js/src/views/Playground/index.js +++ b/js/src/views/Playground/index.js @@ -21,9 +21,10 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Playground/playground.js b/js/src/views/Playground/playground.js index 9aa32f5c0..c7b431643 100644 --- a/js/src/views/Playground/playground.js +++ b/js/src/views/Playground/playground.js @@ -19,74 +19,61 @@ import React, { Component } from 'react'; import AccountCard from '~/ui/AccountCard/accountCard.example'; import CurrencySymbol from '~/ui/CurrencySymbol/currencySymbol.example'; +import Portal from '~/ui/Portal/portal.example'; import QrCode from '~/ui/QrCode/qrCode.example'; import SectionList from '~/ui/SectionList/sectionList.example'; -import Portal from '~/ui/Portal/portal.example'; import PlaygroundStore from './store'; import styles from './playground.css'; PlaygroundStore.register(); PlaygroundStore.register(); +PlaygroundStore.register(); PlaygroundStore.register(); PlaygroundStore.register(); -PlaygroundStore.register(); @observer export default class Playground extends Component { - state = { - selectedIndex: 0 - }; - store = PlaygroundStore.get(); render () { + const { component, components } = this.store; + return (
- Playground > + Playground -
- { this.renderComponent() } + { component }
); } - renderOptions () { - const { components } = this.store; - - return components.map((element, index) => { - const name = element.type.displayName || element.type.name; - - return ( - - ); - }); - } - - renderComponent () { - const { components } = this.store; - const { selectedIndex } = this.state; - - return components[selectedIndex]; - } - handleChange = (event) => { const { value } = event.target; - this.setState({ selectedIndex: value }); + this.store.setSelectedIndex(value); } } diff --git a/js/src/views/Playground/playgroundExample.js b/js/src/views/Playground/playgroundExample.js index 9d16ef3ff..8a4dae283 100644 --- a/js/src/views/Playground/playgroundExample.js +++ b/js/src/views/Playground/playgroundExample.js @@ -14,42 +14,32 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import reactElementToJSXString from 'react-element-to-jsx-string'; import styles from './playground.css'; -export default class PlaygroundExample extends Component { - static propTypes = { - children: PropTypes.node, - name: PropTypes.string - }; - - render () { - const { children, name } = this.props; - - return ( -
- { this.renderName(name) } -
-
- { reactElementToJSXString(children) } -
-
- { children } -
+export default function PlaygroundExample ({ children, name }) { + return ( +
+ { + name + ?

{ name }

+ : null + } +
+
+ { reactElementToJSXString(children) } +
+
+ { children }
- ); - } - - renderName (name) { - if (!name) { - return null; - } - - return ( -

{ name }

- ); - } +
+ ); } + +PlaygroundExample.propTypes = { + children: PropTypes.node, + name: PropTypes.string +}; diff --git a/js/src/views/Playground/store.js b/js/src/views/Playground/store.js index db0df38b4..c2d7cb929 100644 --- a/js/src/views/Playground/store.js +++ b/js/src/views/Playground/store.js @@ -14,12 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { action } from 'mobx'; +import { action, computed, observable } from 'mobx'; let instance = null; export default class PlaygroundStore { - components = []; + @observable components = []; + @observable selectedIndex = 0; + + @computed get component () { + return this.components[this.selectedIndex]; + } + + @action add (component) { + this.components.push(component); + } + + @action setSelectedIndex (selectedIndex) { + this.selectedIndex = selectedIndex; + } static get () { if (!instance) { @@ -32,9 +45,4 @@ export default class PlaygroundStore { static register (component) { PlaygroundStore.get().add(component); } - - @action - add (component) { - this.components.push(component); - } } diff --git a/js/src/views/Settings/Background/background.js b/js/src/views/Settings/Background/background.js index dd348a4c4..ffdc0dd9d 100644 --- a/js/src/views/Settings/Background/background.js +++ b/js/src/views/Settings/Background/background.js @@ -19,12 +19,12 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { updateBackground } from '@parity/shared/redux/providers/settings/actions'; + import { Button, Container } from '~/ui'; import ParityBackground from '~/ui/ParityBackground'; import { RefreshIcon } from '~/ui/Icons'; -import { updateBackground } from '~/redux/providers/settings/actions'; - import layout from '../layout.css'; import styles from './background.css'; diff --git a/js/src/views/Settings/Node/index.js b/js/src/views/Settings/Node/index.js index 7fe520c60..cc01337ff 100644 --- a/js/src/views/Settings/Node/index.js +++ b/js/src/views/Settings/Node/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default from './parity'; +export default from './node'; diff --git a/js/src/views/Settings/Node/parity.js b/js/src/views/Settings/Node/node.js similarity index 97% rename from js/src/views/Settings/Node/parity.js rename to js/src/views/Settings/Node/node.js index aad2fa1c9..9fa403e10 100644 --- a/js/src/views/Settings/Node/parity.js +++ b/js/src/views/Settings/Node/node.js @@ -26,7 +26,7 @@ import Store, { LOGLEVEL_OPTIONS } from './store'; import layout from '../layout.css'; @observer -export default class Parity extends Component { +export default class Node extends Component { static contextTypes = { api: PropTypes.object.isRequired }; @@ -71,7 +71,7 @@ export default class Parity extends Component { return ( @@ -139,10 +139,13 @@ export default class Parity extends Component { /> - + { this.renderItem('active', this.onChangeMode, ( @@ -194,7 +197,7 @@ export default class Parity extends Component { /> diff --git a/js/src/views/Settings/Node/parity.spec.js b/js/src/views/Settings/Node/node.spec.js similarity index 79% rename from js/src/views/Settings/Node/parity.spec.js rename to js/src/views/Settings/Node/node.spec.js index 8b5ff61eb..7b37f8025 100644 --- a/js/src/views/Settings/Node/parity.spec.js +++ b/js/src/views/Settings/Node/node.spec.js @@ -18,23 +18,24 @@ import { shallow } from 'enzyme'; import React from 'react'; import sinon from 'sinon'; -import { createApi } from './parity.test.js'; -import Parity from './'; +import { createApi } from './node.test.js'; +import Node from './'; let component; let instance; function render (props = {}) { component = shallow( - , + , { context: { api: createApi() } } ); instance = component.instance(); + // console.log(component.debug()); return component; } -describe('views/Settings/Parity', () => { +describe('views/Settings/Node', () => { beforeEach(() => { render(); sinon.spy(instance.store, 'loadMode'); @@ -83,7 +84,7 @@ describe('views/Settings/Parity', () => { let select; beforeEach(() => { - select = component.find('Select[id="parityModeSelect"]'); + select = component.find('Menu[id="parityModeSelect"]'); sinon.spy(instance.store, 'changeMode'); }); @@ -94,18 +95,13 @@ describe('views/Settings/Parity', () => { it('renders a mode selector', () => { expect(select).to.have.length(1); }); - - it('changes the mode on the store when changed', () => { - select.simulate('change', { target: { value: 'dark' } }); - expect(instance.store.changeMode).to.have.been.calledWith('dark'); - }); }); describe('chain selector', () => { let select; beforeEach(() => { - select = component.find('Select[id="parityChainSelect"]'); + select = component.find('Menu[id="parityChainSelect"]'); sinon.spy(instance.store, 'changeChain'); }); @@ -116,11 +112,6 @@ describe('views/Settings/Parity', () => { it('renders a chain selector', () => { expect(select).to.have.length(1); }); - - it('changes the chain on the store when changed', () => { - select.simulate('change', { target: { value: 'dark' } }); - expect(instance.store.changeChain).to.have.been.calledWith('dark'); - }); }); }); }); diff --git a/js/src/views/Settings/Node/parity.test.js b/js/src/views/Settings/Node/node.test.js similarity index 100% rename from js/src/views/Settings/Node/parity.test.js rename to js/src/views/Settings/Node/node.test.js diff --git a/js/src/views/Settings/Node/store.js b/js/src/views/Settings/Node/store.js index 6b9c477e8..98e8f228a 100644 --- a/js/src/views/Settings/Node/store.js +++ b/js/src/views/Settings/Node/store.js @@ -17,7 +17,7 @@ import LogLevel from 'loglevel'; import { action, observable } from 'mobx'; -import { LOG_KEYS } from '~/config'; +import { LOG_KEYS } from '@parity/shared/config'; const DEFAULT_MODE = 'active'; const DEFAULT_CHAIN = 'foundation'; diff --git a/js/src/views/Settings/Node/store.spec.js b/js/src/views/Settings/Node/store.spec.js index f965b9c44..356430586 100644 --- a/js/src/views/Settings/Node/store.spec.js +++ b/js/src/views/Settings/Node/store.spec.js @@ -16,7 +16,7 @@ import sinon from 'sinon'; -import { createApi } from './parity.test.js'; +import { createApi } from './node.test.js'; import Store from './store'; let api; diff --git a/js/src/views/Settings/Views/views.js b/js/src/views/Settings/Views/views.js index 771ecdf04..12df810be 100644 --- a/js/src/views/Settings/Views/views.js +++ b/js/src/views/Settings/Views/views.js @@ -19,9 +19,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { Checkbox, Container } from '~/ui'; +import { toggleView } from '@parity/shared/redux/providers/settings/actions'; -import { toggleView } from '~/redux/providers/settings/actions'; +import { Checkbox, Container } from '~/ui'; import layout from '../layout.css'; import styles from './views.css'; diff --git a/js/src/views/Settings/index.js b/js/src/views/Settings/index.js index f3ddb6857..da7027867 100644 --- a/js/src/views/Settings/index.js +++ b/js/src/views/Settings/index.js @@ -21,7 +21,8 @@ import { IndexRedirect, Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); -import { initStore } from '~/redux'; +import { initStore } from '@parity/shared/redux'; + import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Signer/RequestsPage/requestsPage.js b/js/src/views/Signer/RequestsPage/requestsPage.js index 4d0bf8180..406526d06 100644 --- a/js/src/views/Signer/RequestsPage/requestsPage.js +++ b/js/src/views/Signer/RequestsPage/requestsPage.js @@ -21,8 +21,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; -import { startConfirmRequest, startRejectRequest } from '~/redux/providers/signerActions'; +import { newError } from '@parity/shared/redux/actions'; +import { startConfirmRequest, startRejectRequest } from '@parity/shared/redux/providers/signerActions'; + import { Container, Page, TxList } from '~/ui'; import Store from '~/shell/Signer/store'; diff --git a/js/src/views/Signer/index.js b/js/src/views/Signer/index.js index bf6bb67a2..45c1ac775 100644 --- a/js/src/views/Signer/index.js +++ b/js/src/views/Signer/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Status/Debug/Logs/logs.js b/js/src/views/Status/Debug/Logs/logs.js index 420756dea..42ba0b1d0 100644 --- a/js/src/views/Status/Debug/Logs/logs.js +++ b/js/src/views/Status/Debug/Logs/logs.js @@ -16,7 +16,7 @@ import React from 'react'; -import { arrayOrObjectProptype } from '~/util/proptypes'; +import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; import styles from '../debug.css'; diff --git a/js/src/views/Status/Peers/peers.js b/js/src/views/Status/Peers/peers.js index 8ea36e087..1c279b206 100644 --- a/js/src/views/Status/Peers/peers.js +++ b/js/src/views/Status/Peers/peers.js @@ -20,7 +20,7 @@ import { connect } from 'react-redux'; import { Container } from '~/ui'; -import Peer from './peer'; +import Peer from './Peer'; import styles from './peers.css'; diff --git a/js/src/views/Status/index.js b/js/src/views/Status/index.js index 17432a774..b82492d54 100644 --- a/js/src/views/Status/index.js +++ b/js/src/views/Status/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Vaults/VaultAccounts/vaultAccounts.js b/js/src/views/Vaults/VaultAccounts/vaultAccounts.js index daf2d7c51..08ca5ad40 100644 --- a/js/src/views/Vaults/VaultAccounts/vaultAccounts.js +++ b/js/src/views/Vaults/VaultAccounts/vaultAccounts.js @@ -20,8 +20,9 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; -import { personalAccountsInfo } from '~/redux/providers/personalActions'; +import { newError } from '@parity/shared/redux/actions'; +import { personalAccountsInfo } from '@parity/shared/redux/providers/personalActions'; + import { AccountCard, Button, Portal, SelectionList } from '~/ui'; import { CancelIcon, CheckIcon } from '~/ui/Icons'; diff --git a/js/src/views/Vaults/VaultCreate/vaultCreate.js b/js/src/views/Vaults/VaultCreate/vaultCreate.js index c472b28d0..b95aa354e 100644 --- a/js/src/views/Vaults/VaultCreate/vaultCreate.js +++ b/js/src/views/Vaults/VaultCreate/vaultCreate.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { Button, Input, Portal } from '~/ui'; import PasswordStrength from '~/ui/Form/PasswordStrength'; import { CheckIcon, CloseIcon } from '~/ui/Icons'; diff --git a/js/src/views/Vaults/VaultLock/vaultLock.js b/js/src/views/Vaults/VaultLock/vaultLock.js index 74135d544..e809e2d45 100644 --- a/js/src/views/Vaults/VaultLock/vaultLock.js +++ b/js/src/views/Vaults/VaultLock/vaultLock.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { ConfirmDialog, VaultCard } from '~/ui'; import styles from '../VaultUnlock/vaultUnlock.css'; diff --git a/js/src/views/Vaults/VaultMeta/vaultMeta.js b/js/src/views/Vaults/VaultMeta/vaultMeta.js index a87b57494..b41374f2d 100644 --- a/js/src/views/Vaults/VaultMeta/vaultMeta.js +++ b/js/src/views/Vaults/VaultMeta/vaultMeta.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { Button, Checkbox, Form, Input, Portal, VaultCard } from '~/ui'; import PasswordStrength from '~/ui/Form/PasswordStrength'; import { CheckIcon, CloseIcon } from '~/ui/Icons'; diff --git a/js/src/views/Vaults/VaultUnlock/vaultUnlock.js b/js/src/views/Vaults/VaultUnlock/vaultUnlock.js index 3c1eaddc0..ecc56a6c0 100644 --- a/js/src/views/Vaults/VaultUnlock/vaultUnlock.js +++ b/js/src/views/Vaults/VaultUnlock/vaultUnlock.js @@ -20,7 +20,8 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { newError } from '~/redux/actions'; +import { newError } from '@parity/shared/redux/actions'; + import { ConfirmDialog, Form, Input, VaultCard } from '~/ui'; import styles from './vaultUnlock.css'; diff --git a/js/src/views/Vaults/index.js b/js/src/views/Vaults/index.js index e92e39a5c..a0602cf40 100644 --- a/js/src/views/Vaults/index.js +++ b/js/src/views/Vaults/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Vaults/store.spec.js b/js/src/views/Vaults/store.spec.js index caac26eae..4d7b7bf02 100644 --- a/js/src/views/Vaults/store.spec.js +++ b/js/src/views/Vaults/store.spec.js @@ -16,7 +16,7 @@ import sinon from 'sinon'; -import Vaults from './'; +import Vaults from './vaults'; import ERRORS from '~/views/Accounts/CreateAccount/errors'; import { createApi, TEST_VAULTS_ALL, TEST_VAULTS_META, TEST_VAULTS_OPEN } from './vaults.test.js'; diff --git a/js/src/views/Vaults/vaults.spec.js b/js/src/views/Vaults/vaults.spec.js index 1f1fd449d..4748f91bd 100644 --- a/js/src/views/Vaults/vaults.spec.js +++ b/js/src/views/Vaults/vaults.spec.js @@ -20,7 +20,7 @@ import sinon from 'sinon'; import { createApi, createReduxStore } from './vaults.test.js'; -import Vaults from './'; +import Vaults from './vaults'; let api; let component; diff --git a/js/src/views/Wallet/Confirmations/confirmations.js b/js/src/views/Wallet/Confirmations/confirmations.js index 01b4551d3..2724de69d 100644 --- a/js/src/views/Wallet/Confirmations/confirmations.js +++ b/js/src/views/Wallet/Confirmations/confirmations.js @@ -22,8 +22,8 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { bytesToHex } from '@parity/api/util/format'; +import { confirmOperation, revokeOperation } from '@parity/shared/redux/providers/walletActions'; -import { confirmOperation, revokeOperation } from '~/redux/providers/walletActions'; import { Button, Container, InputAddress, IdentityIcon, Progress } from '~/ui'; import TxRow from '~/ui/TxList/TxRow'; diff --git a/js/src/views/Wallet/WalletSettings/walletSettings.js b/js/src/views/Wallet/WalletSettings/walletSettings.js index 73d821530..2bf7ac3b5 100644 --- a/js/src/views/Wallet/WalletSettings/walletSettings.js +++ b/js/src/views/Wallet/WalletSettings/walletSettings.js @@ -247,8 +247,6 @@ class WalletSettings extends Component { } renderChange (change) { - const { accountsInfo } = this.props; - switch (change.type) { case 'dailylimit': return ( @@ -279,14 +277,50 @@ class WalletSettings extends Component { id='walletSettings.ownersChange.details' defaultMessage=' from {from} to {to} ' values={ { - from: change.initial.toNumber(), - to: change.value.toNumber() + from: { change.initial.toNumber() }, + to: { change.value.toNumber() } } } />
); + case 'change_owner': + return ( +
+
+ +
+
+ + } + text + value={ change.value.from } + /> + + } + text + value={ change.value.to } + /> +
+
+ ); + case 'add_owner': return (
@@ -299,8 +333,8 @@ class WalletSettings extends Component {
@@ -318,8 +352,8 @@ class WalletSettings extends Component {
diff --git a/js/src/views/Wallet/WalletSettings/walletSettingsStore.js b/js/src/views/Wallet/WalletSettings/walletSettingsStore.js index b4ae8fc9a..cfc448617 100644 --- a/js/src/views/Wallet/WalletSettings/walletSettingsStore.js +++ b/js/src/views/Wallet/WalletSettings/walletSettingsStore.js @@ -18,8 +18,8 @@ import { noop } from 'lodash'; import { observable, computed, action, transaction } from 'mobx'; import BigNumber from 'bignumber.js'; -import { validateUint, validateAddress } from '~/util/validation'; -import { DEFAULT_GAS, MAX_GAS_ESTIMATION } from '~/util/constants'; +import { validateUint, validateAddress } from '@parity/shared/util/validation'; +import { DEFAULT_GAS, MAX_GAS_ESTIMATION } from '@parity/shared/util/constants'; const STEPS = { EDIT: { title: 'wallet settings' }, @@ -78,12 +78,16 @@ export default class WalletSettingsStore { const changes = data.map((datum) => { const [ type, valueStr ] = datum.split(';'); - let value = valueStr; + let value; - // Only addresses start with `0x`, the others - // are BigNumbers - if (!/^0x/.test(valueStr)) { - value = new BigNumber(valueStr, 16); + if (/^#BN#/.test(valueStr)) { + value = new BigNumber(valueStr.replace(/^#BN#/, ''), 16); + } else { + try { + value = JSON.parse(valueStr); + } catch (e) { + value = valueStr; + } } return { type, value }; @@ -104,8 +108,8 @@ export default class WalletSettingsStore { const { type, value } = change; const valueStr = (value && typeof value.plus === 'function') - ? value.toString(16) - : value; + ? '#BN#' + value.toString(16) + : JSON.stringify(value); return [ type, @@ -147,14 +151,26 @@ export default class WalletSettingsStore { const ownersToRemove = prevOwners.filter((owner) => !nextOwners.includes(owner)); const ownersToAdd = nextOwners.filter((owner) => !prevOwners.includes(owner)); - ownersToRemove.forEach((owner) => { + const ownersChangeCount = Math.min(ownersToRemove.length, ownersToAdd.length); + + for (let i = 0; i < ownersChangeCount; i++) { + changes.push({ + type: 'change_owner', + value: { + from: ownersToRemove[i], + to: ownersToAdd[i] + } + }); + } + + ownersToRemove.slice(ownersChangeCount).forEach((owner) => { changes.push({ type: 'remove_owner', value: owner }); }); - ownersToAdd.forEach((owner) => { + ownersToAdd.slice(ownersChangeCount).forEach((owner) => { changes.push({ type: 'add_owner', value: owner @@ -182,6 +198,12 @@ export default class WalletSettingsStore { this.wallet.require = value; break; + case 'change_owner': + this.wallet.owners = this.wallet.owners + .filter((owner) => owner !== value.from) + .concat(value.to); + break; + case 'remove_owner': this.wallet.owners = this.wallet.owners.filter((owner) => owner !== value); break; @@ -309,6 +331,13 @@ export default class WalletSettingsStore { }; } + if (change.type === 'change_owner') { + return { + method: walletInstance.changeOwner, + values: [ change.value.from, change.value.to ] + }; + } + if (change.type === 'remove_owner') { return { method: walletInstance.removeOwner, diff --git a/js/src/views/Wallet/index.js b/js/src/views/Wallet/index.js index c68b0ca68..85010ac32 100644 --- a/js/src/views/Wallet/index.js +++ b/js/src/views/Wallet/index.js @@ -21,10 +21,11 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import ContractInstances from '@parity/shared/contracts'; +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import ContractInstances from '~/contracts'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Wallet/wallet.js b/js/src/views/Wallet/wallet.js index f4b265a8b..490b4faa6 100644 --- a/js/src/views/Wallet/wallet.js +++ b/js/src/views/Wallet/wallet.js @@ -20,10 +20,12 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import moment from 'moment'; -import HistoryStore from '~/mobx/historyStore'; +import HistoryStore from '@parity/shared/mobx/historyStore'; +import { setVisibleAccounts } from '@parity/shared/redux/providers/personalActions'; +import { nullableProptype } from '@parity/shared/util/proptypes'; + import { Actionbar, Button, Page, Loading } from '~/ui'; import { DeleteIcon, EditIcon, SendIcon, SettingsIcon } from '~/ui/Icons'; -import { nullableProptype } from '~/util/proptypes'; import EditMeta from '../Account/EditMeta'; import Transfer from '../Account/Transfer'; @@ -34,8 +36,6 @@ import WalletConfirmations from './Confirmations'; import WalletTransactions from './Transactions'; import WalletSettings from './WalletSettings'; -import { setVisibleAccounts } from '~/redux/providers/personalActions'; - import styles from './wallet.css'; const accountsHistory = HistoryStore.get('accounts'); diff --git a/js/src/views/Web/dapplink.js b/js/src/views/Web/dapplink.js index 010beb7d9..e03ed0d02 100644 --- a/js/src/views/Web/dapplink.js +++ b/js/src/views/Web/dapplink.js @@ -16,7 +16,7 @@ import base32 from 'base32.js'; -import { DOMAIN } from '~/util/constants'; +import { DOMAIN } from '@parity/shared/util/constants'; const BASE_URL = `.web${DOMAIN}`; const ENCODER_OPTS = { type: 'crockford' }; diff --git a/js/src/views/Web/index.js b/js/src/views/Web/index.js index d7db0069c..fd894e6d0 100644 --- a/js/src/views/Web/index.js +++ b/js/src/views/Web/index.js @@ -21,9 +21,10 @@ import { Route, Router, hashHistory } from 'react-router'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); +import { initStore } from '@parity/shared/redux'; + import { api } from './parity'; -import { initStore } from '~/redux'; import ContextProvider from '~/ui/ContextProvider'; import muiTheme from '~/ui/Theme'; diff --git a/js/src/views/Web/web.spec.js b/js/src/views/Web/web.spec.js index 950806d0b..8729cbf61 100644 --- a/js/src/views/Web/web.spec.js +++ b/js/src/views/Web/web.spec.js @@ -18,7 +18,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import { DEFAULT_URL } from './store'; -import Web from './'; +import Web from './web'; let api; let component; diff --git a/js/src/views/package.json b/js/src/views/package.json new file mode 100644 index 000000000..4877cbcfc --- /dev/null +++ b/js/src/views/package.json @@ -0,0 +1,19 @@ +{ + "name": "@parity/view", + "description": "Parity wallet dapps", + "version": "0.0.0", + "main": "index.js", + "author": "Parity Team ", + "maintainers": [], + "contributors": [], + "license": "GPL-3.0", + "repository": { + "type": "git", + "url": "git+https://github.com/paritytech/parity.git" + }, + "keywords": [], + "scripts": {}, + "devDependencies": {}, + "dependencies": {}, + "peerDependencies": {} +} diff --git a/js/src/util/web3.extensions.js b/js/src/web3.extensions.js similarity index 89% rename from js/src/util/web3.extensions.js rename to js/src/web3.extensions.js index fc9fe06b5..bccf138c7 100644 --- a/js/src/util/web3.extensions.js +++ b/js/src/web3.extensions.js @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import parity from '~/jsonrpc/interfaces/parity'; -import signer from '~/jsonrpc/interfaces/signer'; -import trace from '~/jsonrpc/interfaces/trace'; +import parity from '@parity/jsonrpc/interfaces/parity'; +import signer from '@parity/jsonrpc/interfaces/signer'; +import trace from '@parity/jsonrpc/interfaces/trace'; export default function web3extensions (web3) { const { Method } = web3._extend; diff --git a/js/src/web3.js b/js/src/web3.js index 89a411427..c818084bb 100644 --- a/js/src/web3.js +++ b/js/src/web3.js @@ -15,7 +15,7 @@ // along with Parity. If not, see . import Web3 from 'web3'; -import web3extensions from './util/web3.extensions'; +import web3extensions from './web3.extensions'; import './dev.web3.html'; diff --git a/js/src/webWorker.js b/js/src/webWorker.js index 838382acf..95719d7e1 100644 --- a/js/src/webWorker.js +++ b/js/src/webWorker.js @@ -15,14 +15,18 @@ // along with Parity. If not, see . import registerPromiseWorker from 'promise-worker/register'; -import { Signer } from '~/util/signer'; -import SolidityUtils from '~/util/solidity'; + +import { Signer } from '@parity/shared/util/signer'; +import SolidityUtils from '@parity/shared/util/solidity'; registerPromiseWorker((msg) => { return handleMessage(msg); }); -self.solc = {}; +self.compiler = { + version: null, + compiler: null +}; self.files = {}; function handleMessage (message) { @@ -57,7 +61,16 @@ function compile (data) { return getCompiler(build) .then((compiler) => { + console.warn('compiling'); return SolidityUtils.compile(data, compiler); + }) + .then((result) => { + console.warn('result in worker', result); + return result; + }) + .catch((error) => { + console.error('error in worker', error); + throw error; }); } @@ -79,14 +92,18 @@ function setFiles (files) { function getCompiler (build) { const { longVersion } = build; - if (!self.solc[longVersion]) { - self.solc[longVersion] = SolidityUtils + if (self.compiler.version !== longVersion) { + self.compiler.version = longVersion; + self.compiler.compiler = SolidityUtils .getCompiler(build) .then((compiler) => { - self.solc[longVersion] = compiler; + if (self.compiler.version === longVersion) { + self.compiler.compiler = compiler; + } + return compiler; }); } - return Promise.resolve(self.solc[longVersion]); + return Promise.resolve(self.compiler.compiler); } diff --git a/js/test/babel.js b/js/test/babel.js index 95a988d42..e0c6e5f9c 100644 --- a/js/test/babel.js +++ b/js/test/babel.js @@ -15,5 +15,5 @@ // along with Parity. If not, see . require('babel-register')({ - ignore: /node_modules\/(?!@parity\/(abi|api|jsonrpc))/ + ignore: /node_modules\/(?!@parity\/(abi|api|jsonrpc|shared|ui))/ }); diff --git a/js/test/types.js b/js/test/types.js index ced405147..181f742cb 100644 --- a/js/test/types.js +++ b/js/test/types.js @@ -15,9 +15,10 @@ // along with Parity. If not, see . import BigNumber from 'bignumber.js'; + import { isInstanceOf } from '../src/api/util/types'; -export { isFunction, isInstanceOf } from '../src/api/util/types'; +export { isFunction, isInstanceOf } from '../src/api/util/types'; // eslint-disable-line no-duplicate-imports export { isAddress } from '../src/abi/util/address'; const ZEROS = '000000000000000000000000000000000000000000000000000000000000'; diff --git a/js/webpack/app.js b/js/webpack/app.js index f88afb2c0..607786c38 100644 --- a/js/webpack/app.js +++ b/js/webpack/app.js @@ -29,11 +29,11 @@ const rulesEs6 = require('./rules/es6'); const rulesParity = require('./rules/parity'); const Shared = require('./shared'); -const DAPPS_BUILTIN = require('../src/config/dappsBuiltin.json').map((dapp) => { +const DAPPS_BUILTIN = require('../src/shared/config/dappsBuiltin.json').map((dapp) => { dapp.srcPath = './dapps'; return dapp; }); -const DAPPS_VIEWS = require('../src/config/dappsViews.json').map((dapp) => { +const DAPPS_VIEWS = require('../src/shared/config/dappsViews.json').map((dapp) => { dapp.srcPath = './views'; dapp.commons = true; return dapp; diff --git a/js/webpack/rules/es6.js b/js/webpack/rules/es6.js index 8e485424e..4e6edd2c9 100644 --- a/js/webpack/rules/es6.js +++ b/js/webpack/rules/es6.js @@ -16,6 +16,6 @@ module.exports = { test: /\.js$/, - include: /node_modules\/(material-chip-input|ethereumjs-tx)/, + include: /node_modules\/(get-own-enumerable-property-symbols|material-chip-input|ethereumjs-tx|stringify-object)/, use: 'babel-loader' }; diff --git a/js/webpack/rules/parity.js b/js/webpack/rules/parity.js index 34ec31419..7686a06c8 100644 --- a/js/webpack/rules/parity.js +++ b/js/webpack/rules/parity.js @@ -16,6 +16,6 @@ module.exports = { test: /\.js$/, - include: /node_modules\/@parity\/(abi|api|jsonrpc|ui|wordlist)/, + include: /node_modules\/@parity\/(abi|api|jsonrpc|shared|ui|wordlist)/, use: 'babel-loader' }; diff --git a/js/webpack/shared.js b/js/webpack/shared.js index ae39d37da..a56f32b23 100644 --- a/js/webpack/shared.js +++ b/js/webpack/shared.js @@ -151,8 +151,8 @@ function getPlugins (_isProd = isProd) { } function getDappsEntry () { - const builtins = require('../src/config/dappsBuiltin.json'); - const views = require('../src/config/dappsViews.json'); + const builtins = require('../src/shared/config/dappsBuiltin.json'); + const views = require('../src/shared/config/dappsViews.json'); return Object.assign( builtins.filter((dapp) => !dapp.skipBuild).reduce((_entry, dapp) => { diff --git a/local-store/src/lib.rs b/local-store/src/lib.rs index d21ca031d..e975aa43d 100644 --- a/local-store/src/lib.rs +++ b/local-store/src/lib.rs @@ -173,14 +173,26 @@ impl LocalDataStore { pub fn update(&self) -> Result<(), Error> { trace!(target: "local_store", "Updating local store entries."); - let mut batch = self.db.transaction(); - let local_entries: Vec = self.node.pending_transactions() .into_iter() .map(Into::into) .collect(); - let local_json = ::serde_json::to_value(&local_entries).map_err(Error::Json)?; + self.write_txs(&local_entries) + } + + /// Clear data in this column. + pub fn clear(&self) -> Result<(), Error> { + trace!(target: "local_store", "Clearing local store entries."); + + self.write_txs(&[]) + } + + // helper for writing a vector of transaction entries to disk. + fn write_txs(&self, txs: &[TransactionEntry]) -> Result<(), Error> { + let mut batch = self.db.transaction(); + + let local_json = ::serde_json::to_value(txs).map_err(Error::Json)?; let json_str = format!("{}", local_json); batch.put_vec(self.col, LOCAL_TRANSACTIONS_KEY, json_str.into_bytes()); diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml index 64ddd20e9..624c0ccdf 100644 --- a/parity/cli/config.full.toml +++ b/parity/cli/config.full.toml @@ -7,6 +7,7 @@ release_track = "current" public_node = false no_download = false no_consensus = false +no_persistent_txqueue = false chain = "homestead" base_path = "$HOME/.parity" @@ -49,7 +50,7 @@ disable = false port = 8545 interface = "local" cors = "null" -apis = ["web3", "eth", "net", "parity", "traces", "rpc"] +apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] hosts = ["none"] [websockets] @@ -57,13 +58,13 @@ disable = false port = 8546 interface = "local" origins = ["none"] -apis = ["web3", "eth", "net", "parity", "traces", "rpc"] +apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] hosts = ["none"] [ipc] disable = false path = "$HOME/.parity/jsonrpc.ipc" -apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc"] +apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc", "secretstore"] [dapps] disable = false diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 05627b90b..f36622357 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -95,6 +95,8 @@ usage! { flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(), flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(), flag_light: bool = false, or |c: &Config| otry!(c.parity).light, + flag_no_persistent_txqueue: bool = false, + or |c: &Config| otry!(c.parity).no_persistent_txqueue, // -- Account Options flag_unlock: Option = None, @@ -163,7 +165,7 @@ usage! { or |c: &Config| otry!(c.rpc).interface.clone(), flag_jsonrpc_cors: Option = None, or |c: &Config| otry!(c.rpc).cors.clone().map(Some), - flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc", + flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc,secretstore", or |c: &Config| otry!(c.rpc).apis.as_ref().map(|vec| vec.join(",")), flag_jsonrpc_hosts: String = "none", or |c: &Config| otry!(c.rpc).hosts.as_ref().map(|vec| vec.join(",")), @@ -177,7 +179,7 @@ usage! { or |c: &Config| otry!(c.websockets).port.clone(), flag_ws_interface: String = "local", or |c: &Config| otry!(c.websockets).interface.clone(), - flag_ws_apis: String = "web3,eth,net,parity,traces,rpc", + flag_ws_apis: String = "web3,eth,net,parity,traces,rpc,secretstore", or |c: &Config| otry!(c.websockets).apis.as_ref().map(|vec| vec.join(",")), flag_ws_origins: String = "none", or |c: &Config| otry!(c.websockets).origins.as_ref().map(|vec| vec.join(",")), @@ -189,7 +191,7 @@ usage! { or |c: &Config| otry!(c.ipc).disable.clone(), flag_ipc_path: String = "$BASE/jsonrpc.ipc", or |c: &Config| otry!(c.ipc).path.clone(), - flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc", + flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc,secretstore", or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")), // DAPPS @@ -345,7 +347,6 @@ usage! { flag_no_color: bool = false, or |c: &Config| otry!(c.misc).color.map(|c| !c).clone(), - // -- Legacy Options supported in configs flag_dapps_port: Option = None, or |c: &Config| otry!(c.dapps).port.clone().map(Some), @@ -406,6 +407,7 @@ struct Operating { keys_path: Option, identity: Option, light: Option, + no_persistent_txqueue: Option, } #[derive(Default, Debug, PartialEq, RustcDecodable)] @@ -682,6 +684,7 @@ mod tests { flag_keys_path: "$HOME/.parity/keys".into(), flag_identity: "".into(), flag_light: false, + flag_no_persistent_txqueue: false, // -- Account Options flag_unlock: Some("0xdeadbeefcafe0000000000000000000000000000".into()), @@ -720,7 +723,7 @@ mod tests { flag_jsonrpc_port: 8545u16, flag_jsonrpc_interface: "local".into(), flag_jsonrpc_cors: Some("null".into()), - flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc".into(), + flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), flag_jsonrpc_hosts: "none".into(), flag_jsonrpc_threads: None, @@ -728,14 +731,14 @@ mod tests { flag_no_ws: false, flag_ws_port: 8546u16, flag_ws_interface: "local".into(), - flag_ws_apis: "web3,eth,net,parity,traces,rpc".into(), + flag_ws_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), flag_ws_origins: "none".into(), flag_ws_hosts: "none".into(), // IPC flag_no_ipc: false, flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(), - flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc".into(), + flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc,secretstore".into(), // DAPPS flag_dapps_path: "$HOME/.parity/dapps".into(), @@ -901,6 +904,7 @@ mod tests { keys_path: None, identity: None, light: None, + no_persistent_txqueue: None, }), account: Some(Account { unlock: Some(vec!["0x1".into(), "0x2".into(), "0x3".into()]), diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 17b6ce2b8..9d2e4f6d5 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -304,6 +304,9 @@ Sealing/Mining Options: execution time limit. Also number of offending actions have to reach the threshold within that time. (default: {flag_tx_queue_ban_time} seconds) + --no-persistent-txqueue Don't save pending local transactions to disk to be + restored whenever the node restarts. + (default: {flag_no_persistent_txqueue}). --remove-solved Move solved blocks from the work package queue instead of cloning them. This gives a slightly faster import speed, but means that extra solutions diff --git a/parity/configuration.rs b/parity/configuration.rs index 3c3c591c1..9aa0d9753 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -388,6 +388,7 @@ impl Configuration { verifier_settings: verifier_settings, serve_light: !self.args.flag_no_serve_light, light: self.args.flag_light, + no_persistent_txqueue: self.args.flag_no_persistent_txqueue, }; Cmd::Run(run_cmd) }; @@ -1270,6 +1271,7 @@ mod tests { verifier_settings: Default::default(), serve_light: true, light: false, + no_persistent_txqueue: false, }; expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(expected)); diff --git a/parity/rpc.rs b/parity/rpc.rs index 1fc503767..2ac93baf7 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -22,7 +22,7 @@ use dir::default_data_path; use parity_rpc::informant::{RpcStats, Middleware}; use parity_rpc::{self as rpc, HttpServerError, Metadata, Origin, DomainsValidation}; use helpers::parity_ipc_path; -use jsonrpc_core::MetaIoHandler; +use jsonrpc_core::{futures, MetaIoHandler}; use parity_reactor::TokioRemote; use rpc_apis::{self, ApiSet}; @@ -126,11 +126,53 @@ impl rpc::IpcMetaExtractor for RpcExtractor { } } -impl rpc::ws::MetaExtractor for RpcExtractor { +struct Sender(rpc::ws::ws::Sender, futures::sync::mpsc::Receiver); + +impl futures::Future for Sender { + type Item = (); + type Error = (); + + fn poll(&mut self) -> futures::Poll { + use self::futures::Stream; + + let item = self.1.poll()?; + match item { + futures::Async::NotReady => { + Ok(futures::Async::NotReady) + }, + futures::Async::Ready(None) => { + Ok(futures::Async::Ready(())) + }, + futures::Async::Ready(Some(val)) => { + if let Err(e) = self.0.send(val) { + warn!("Error sending a subscription update: {:?}", e); + } + self.poll() + }, + } + } +} + +struct WsRpcExtractor { + remote: TokioRemote, +} + +impl WsRpcExtractor { + fn wrap_out(&self, out: rpc::ws::ws::Sender) -> futures::sync::mpsc::Sender { + let (sender, receiver) = futures::sync::mpsc::channel(8); + self.remote.spawn(move |_| Sender(out, receiver)); + sender + } +} + +impl rpc::ws::MetaExtractor for WsRpcExtractor { fn extract(&self, req: &rpc::ws::RequestContext) -> Metadata { let mut metadata = Metadata::default(); let id = req.session_id as u64; metadata.origin = Origin::Ws(id.into()); + metadata.session = Some(Arc::new(rpc::PubSubSession::new( + self.wrap_out(req.out.clone()) + ))); metadata } } @@ -173,10 +215,12 @@ pub fn new_ws( let start_result = rpc::start_ws( &addr, handler, - remote, + remote.clone(), allowed_origins, allowed_hosts, - RpcExtractor, + WsRpcExtractor { + remote: remote, + }, WsStats { stats: deps.stats.clone(), }, @@ -247,7 +291,14 @@ pub fn new_ipc( let handler = setup_apis(conf.apis, dependencies); let remote = dependencies.remote.clone(); - match rpc::start_ipc(&conf.socket_addr, handler, remote, RpcExtractor) { + let ipc = rpc::start_ipc( + &conf.socket_addr, + handler, + remote, + RpcExtractor, + ); + + match ipc { Ok(server) => Ok(Some(server)), Err(io_error) => Err(format!("IPC error: {}", io_error)), } diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 7643e0010..48e66e322 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -31,11 +31,12 @@ use parity_rpc::informant::{ActivityNotifier, Middleware, RpcStats, ClientNotifi use parity_rpc::dispatch::{FullDispatcher, LightDispatcher}; use ethsync::{ManageNetwork, SyncProvider, LightSync}; use hash_fetch::fetch::Client as FetchClient; -use jsonrpc_core::{MetaIoHandler}; +use jsonrpc_core::{self as core, MetaIoHandler}; use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache}; use updater::Updater; use util::{Mutex, RwLock}; use ethcore_logger::RotatingLogger; +use parity_reactor; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Api { @@ -59,6 +60,8 @@ pub enum Api { Traces, /// Rpc (Safe) Rpc, + /// SecretStore (Safe) + SecretStore, } impl FromStr for Api { @@ -78,6 +81,7 @@ impl FromStr for Api { "parity_set" => Ok(ParitySet), "traces" => Ok(Traces), "rpc" => Ok(Rpc), + "secretstore" => Ok(SecretStore), api => Err(format!("Unknown api: {}", api)) } } @@ -156,6 +160,7 @@ fn to_modules(apis: &[Api]) -> BTreeMap { Api::ParitySet => ("parity_set", "1.0"), Api::Traces => ("traces", "1.0"), Api::Rpc => ("rpc", "1.0"), + Api::SecretStore => ("secretstore", "1.0"), }; modules.insert(name.into(), version.into()); } @@ -191,18 +196,16 @@ pub struct FullDependencies { pub dapps_interface: Option, pub dapps_port: Option, pub fetch: FetchClient, + pub remote: parity_reactor::Remote, } -impl Dependencies for FullDependencies { - type Notifier = ClientNotifier; - - fn activity_notifier(&self) -> ClientNotifier { - ClientNotifier { - client: self.client.clone(), - } - } - - fn extend_with_set(&self, handler: &mut MetaIoHandler, apis: &[Api]) { +impl FullDependencies { + fn extend_api>( + &self, + handler: &mut MetaIoHandler, + apis: &[Api], + for_generic_pubsub: bool, + ) { use parity_rpc::v1::*; macro_rules! add_signing_methods { @@ -244,10 +247,12 @@ impl Dependencies for FullDependencies { ); handler.extend_with(client.to_delegate()); - let filter_client = EthFilterClient::new(self.client.clone(), self.miner.clone()); - handler.extend_with(filter_client.to_delegate()); + if !for_generic_pubsub { + let filter_client = EthFilterClient::new(self.client.clone(), self.miner.clone()); + handler.extend_with(filter_client.to_delegate()); - add_signing_methods!(EthSigning, handler, self); + add_signing_methods!(EthSigning, handler, self); + } }, Api::Personal => { handler.extend_with(PersonalClient::new(&self.secret_store, dispatcher.clone(), self.geth_compatibility).to_delegate()); @@ -274,8 +279,14 @@ impl Dependencies for FullDependencies { self.dapps_port, ).to_delegate()); - add_signing_methods!(EthSigning, handler, self); - add_signing_methods!(ParitySigning, handler, self); + if !for_generic_pubsub { + let mut rpc = MetaIoHandler::default(); + self.extend_api(&mut rpc, apis, true); + handler.extend_with(PubSubClient::new(rpc, self.remote.clone()).to_delegate()); + + add_signing_methods!(EthSigning, handler, self); + add_signing_methods!(ParitySigning, handler, self); + } }, Api::ParityAccounts => { handler.extend_with(ParityAccountsClient::new(&self.secret_store).to_delegate()); @@ -295,12 +306,29 @@ impl Dependencies for FullDependencies { Api::Rpc => { let modules = to_modules(&apis); handler.extend_with(RpcClient::new(modules).to_delegate()); - } + }, + Api::SecretStore => { + handler.extend_with(SecretStoreClient::new(&self.secret_store).to_delegate()); + }, } } } } +impl Dependencies for FullDependencies { + type Notifier = ClientNotifier; + + fn activity_notifier(&self) -> ClientNotifier { + ClientNotifier { + client: self.client.clone(), + } + } + + fn extend_with_set(&self, handler: &mut MetaIoHandler>, apis: &[Api]) { + self.extend_api(handler, apis, false) + } +} + /// Light client notifier. Doesn't do anything yet, but might in the future. pub struct LightClientNotifier; @@ -424,7 +452,11 @@ impl Dependencies for LightDependencies { Api::Rpc => { let modules = to_modules(&apis); handler.extend_with(RpcClient::new(modules).to_delegate()); - } + }, + Api::SecretStore => { + let secret_store = Some(self.secret_store.clone()); + handler.extend_with(SecretStoreClient::new(&secret_store).to_delegate()); + }, } } } @@ -438,7 +470,7 @@ impl ApiSet { pub fn list_apis(&self) -> HashSet { let mut public_list = vec![ - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc, Api::SecretStore, ].into_iter().collect(); match *self { ApiSet::List(ref apis) => apis.clone(), @@ -496,6 +528,7 @@ mod test { assert_eq!(Api::ParitySet, "parity_set".parse().unwrap()); assert_eq!(Api::Traces, "traces".parse().unwrap()); assert_eq!(Api::Rpc, "rpc".parse().unwrap()); + assert_eq!(Api::SecretStore, "secretstore".parse().unwrap()); assert!("rp".parse::().is_err()); } @@ -513,7 +546,7 @@ mod test { fn test_api_set_unsafe_context() { let expected = vec![ // make sure this list contains only SAFE methods - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore ].into_iter().collect(); assert_eq!(ApiSet::UnsafeContext.list_apis(), expected); } @@ -522,7 +555,7 @@ mod test { fn test_api_set_ipc_context() { let expected = vec![ // safe - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore, // semi-safe Api::ParityAccounts ].into_iter().collect(); @@ -533,7 +566,7 @@ mod test { fn test_api_set_safe_context() { let expected = vec![ // safe - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore, // semi-safe Api::ParityAccounts, // Unsafe @@ -545,7 +578,7 @@ mod test { #[test] fn test_all_apis() { assert_eq!("all".parse::().unwrap(), ApiSet::List(vec![ - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore, Api::ParityAccounts, Api::ParitySet, Api::Signer, Api::Personal @@ -555,7 +588,7 @@ mod test { #[test] fn test_all_without_personal_apis() { assert_eq!("personal,all,-personal".parse::().unwrap(), ApiSet::List(vec![ - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore, Api::ParityAccounts, Api::ParitySet, Api::Signer, ].into_iter().collect())); @@ -564,7 +597,7 @@ mod test { #[test] fn test_safe_parsing() { assert_eq!("safe".parse::().unwrap(), ApiSet::List(vec![ - Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore, ].into_iter().collect())); } } diff --git a/parity/run.rs b/parity/run.rs index a76c6a4ca..083cbe5ce 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -115,6 +115,7 @@ pub struct RunCmd { pub verifier_settings: VerifierSettings, pub serve_light: bool, pub light: bool, + pub no_persistent_txqueue: bool, } pub fn open_ui(signer_conf: &signer::Configuration) -> Result<(), String> { @@ -142,15 +143,20 @@ pub fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfigur // node info fetcher for the local store. struct FullNodeInfo { - miner: Arc, // TODO: only TXQ needed, just use that after decoupling. + miner: Option>, // TODO: only TXQ needed, just use that after decoupling. } impl ::local_store::NodeInfo for FullNodeInfo { fn pending_transactions(&self) -> Vec<::ethcore::transaction::PendingTransaction> { - let local_txs = self.miner.local_transactions(); - self.miner.pending_transactions() + let miner = match self.miner.as_ref() { + Some(m) => m, + None => return Vec::new(), + }; + + let local_txs = miner.local_transactions(); + miner.pending_transactions() .into_iter() - .chain(self.miner.future_transactions()) + .chain(miner.future_transactions()) .filter(|tx| local_txs.contains_key(&tx.hash())) .collect() } @@ -515,11 +521,22 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R let store = { let db = service.db(); let node_info = FullNodeInfo { - miner: miner.clone(), + miner: match cmd.no_persistent_txqueue { + true => None, + false => Some(miner.clone()), + } }; let store = ::local_store::create(db, ::ethcore::db::COL_NODE_INFO, node_info); + if cmd.no_persistent_txqueue { + info!("Running without a persistent transaction queue."); + + if let Err(e) = store.clear() { + warn!("Error clearing persistent transaction queue: {}", e); + } + } + // re-queue pending transactions. match store.pending_transactions() { Ok(pending) => { @@ -614,6 +631,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R false => None, }, fetch: fetch.clone(), + remote: event_loop.remote(), }); let dependencies = rpc::Dependencies { diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 70ff7202d..b1e2d64aa 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -17,10 +17,12 @@ serde = "0.9" serde_derive = "0.9" serde_json = "0.9" time = "0.1" +tokio-timer = "0.1" transient-hashmap = "0.4" cid = "0.2.1" multihash = "0.5" rust-crypto = "0.2.36" +rand = "0.3" jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } @@ -28,6 +30,7 @@ jsonrpc-minihttp-server = { git = "https://github.com/paritytech/jsonrpc.git", b jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } jsonrpc-ipc-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } +jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } ethcore-io = { path = "../util/io" } ethcore-ipc = { path = "../ipc/rpc" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index ae51d879c..4540d6b33 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -26,15 +26,18 @@ extern crate semver; extern crate serde; extern crate serde_json; extern crate time; +extern crate tokio_timer; extern crate transient_hashmap; extern crate cid; extern crate multihash; extern crate crypto as rust_crypto; +extern crate rand; extern crate jsonrpc_core; extern crate jsonrpc_http_server as http; -extern crate jsonrpc_minihttp_server as minihttp; extern crate jsonrpc_ipc_server as ipc; +extern crate jsonrpc_minihttp_server as minihttp; +extern crate jsonrpc_pubsub; extern crate ethash; extern crate ethcore; @@ -75,6 +78,7 @@ pub extern crate jsonrpc_ws_server as ws; mod metadata; pub mod v1; +pub use jsonrpc_pubsub::Session as PubSubSession; pub use ipc::{Server as IpcServer, MetaExtractor as IpcMetaExtractor, RequestContext as IpcRequestContext}; pub use http::{ hyper, diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 96c38d931..1588be5a9 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -37,6 +37,7 @@ use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, PendingTransaction, Transaction}; use ethcore::account_provider::AccountProvider; +use crypto::DEFAULT_MAC; use jsonrpc_core::Error; use v1::helpers::{errors, TransactionRequest, FilledTransactionRequest, ConfirmationPayload}; @@ -400,9 +401,6 @@ impl Dispatcher for LightDispatcher { } } -/// default MAC to use. -pub const DEFAULT_MAC: [u8; 2] = [0, 0]; - /// Single-use account token. pub type AccountToken = String; diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index b85e6600f..1e26de852 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -25,6 +25,7 @@ pub mod light_fetch; pub mod informant; pub mod oneshot; pub mod ipfs; +pub mod secretstore; mod network_settings; mod poll_manager; @@ -32,6 +33,7 @@ mod poll_filter; mod requests; mod signer; mod signing_queue; +mod subscription_manager; pub use self::dispatch::{Dispatcher, FullDispatcher}; pub use self::network_settings::NetworkSettings; @@ -45,3 +47,4 @@ pub use self::signing_queue::{ QUEUE_LIMIT as SIGNING_QUEUE_LIMIT, }; pub use self::signer::SignerService; +pub use self::subscription_manager::GenericPollManager; diff --git a/rpc/src/v1/helpers/secretstore.rs b/rpc/src/v1/helpers/secretstore.rs new file mode 100644 index 000000000..43c2c8943 --- /dev/null +++ b/rpc/src/v1/helpers/secretstore.rs @@ -0,0 +1,127 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::iter::repeat; +use rand::{Rng, OsRng}; +use ethkey::{Public, Secret, math}; +use crypto; +use util::Bytes; +use jsonrpc_core::Error; +use v1::helpers::errors; + +/// Initialization vector length. +const INIT_VEC_LEN: usize = 16; + +/// Encrypt document with distributely generated key. +pub fn encrypt_document(key: Bytes, document: Bytes) -> Result { + // make document key + let key = into_document_key(key)?; + + // use symmetric encryption to encrypt document + let iv = initialization_vector(); + let mut encrypted_document = Vec::with_capacity(document.len() + iv.len()); + encrypted_document.extend(repeat(0).take(document.len())); + crypto::aes::encrypt(&key, &iv, &document, &mut encrypted_document); + encrypted_document.extend_from_slice(&iv); + + Ok(encrypted_document) +} + +/// Decrypt document with distributely generated key. +pub fn decrypt_document(key: Bytes, mut encrypted_document: Bytes) -> Result { + // initialization vector takes INIT_VEC_LEN bytes + let encrypted_document_len = encrypted_document.len(); + if encrypted_document_len < INIT_VEC_LEN { + return Err(errors::invalid_params("encrypted_document", "invalid encrypted data")); + } + + // make document key + let key = into_document_key(key)?; + + // use symmetric decryption to decrypt document + let iv = encrypted_document.split_off(encrypted_document_len - INIT_VEC_LEN); + let mut document = Vec::with_capacity(encrypted_document_len - INIT_VEC_LEN); + document.extend(repeat(0).take(encrypted_document_len - INIT_VEC_LEN)); + crypto::aes::decrypt(&key, &iv, &encrypted_document, &mut document); + + Ok(document) +} + +pub fn decrypt_document_with_shadow(decrypted_secret: Public, common_point: Public, shadows: Vec, encrypted_document: Bytes) -> Result { + let key = decrypt_with_shadow_coefficients(decrypted_secret, common_point, shadows)?; + decrypt_document(key.to_vec(), encrypted_document) +} + +fn into_document_key(key: Bytes) -> Result { + // key is a previously distributely generated Public + if key.len() != 64 { + return Err(errors::invalid_params("key", "invalid public key length")); + } + + // use x coordinate of distributely generated point as encryption key + Ok(key[..INIT_VEC_LEN].into()) +} + +fn initialization_vector() -> [u8; INIT_VEC_LEN] { + let mut result = [0u8; INIT_VEC_LEN]; + let mut rng = OsRng::new().unwrap(); + rng.fill_bytes(&mut result); + result +} + +fn decrypt_with_shadow_coefficients(mut decrypted_shadow: Public, mut common_shadow_point: Public, shadow_coefficients: Vec) -> Result { + let mut shadow_coefficients_sum = shadow_coefficients[0].clone(); + for shadow_coefficient in shadow_coefficients.iter().skip(1) { + shadow_coefficients_sum.add(shadow_coefficient) + .map_err(errors::encryption_error)?; + } + + math::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum) + .map_err(errors::encryption_error)?; + math::public_add(&mut decrypted_shadow, &common_shadow_point) + .map_err(errors::encryption_error)?; + Ok(decrypted_shadow) +} + +#[cfg(test)] +mod tests { + use util::Bytes; + use rustc_serialize::hex::FromHex; + use super::{encrypt_document, decrypt_document, decrypt_document_with_shadow}; + + #[test] + fn encrypt_and_decrypt_document() { + let document_key: Bytes = "cac6c205eb06c8308d65156ff6c862c62b000b8ead121a4455a8ddeff7248128d895692136f240d5d1614dc7cc4147b1bd584bd617e30560bb872064d09ea325".from_hex().unwrap(); + let document: Bytes = b"Hello, world!!!"[..].into(); + + let encrypted_document = encrypt_document(document_key.clone(), document.clone()).unwrap(); + assert!(document != encrypted_document); + + let decrypted_document = decrypt_document(document_key.clone(), encrypted_document).unwrap(); + assert_eq!(decrypted_document, document); + } + + #[test] + fn encrypt_and_shadow_decrypt_document() { + let document: Bytes = "deadbeef".from_hex().unwrap(); + let encrypted_document = "2ddec1f96229efa2916988d8b2a82a47ef36f71c".from_hex().unwrap(); + let decrypted_secret = "843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91".parse().unwrap(); + let common_point = "07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3".parse().unwrap(); + let shadows = vec!["46f542416216f66a7d7881f5a283d2a1ab7a87b381cbc5f29d0b093c7c89ee31".parse().unwrap()]; + let decrypted_document = decrypt_document_with_shadow(decrypted_secret, common_point, shadows, encrypted_document).unwrap(); + assert_eq!(decrypted_document, document); + } +} diff --git a/rpc/src/v1/helpers/subscription_manager.rs b/rpc/src/v1/helpers/subscription_manager.rs new file mode 100644 index 000000000..4b82fdcc4 --- /dev/null +++ b/rpc/src/v1/helpers/subscription_manager.rs @@ -0,0 +1,175 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Generic poll manager for Pub-Sub. + +use std::sync::Arc; +use std::collections::HashMap; +use util::Mutex; + +use jsonrpc_core::futures::future::{self, Either}; +use jsonrpc_core::futures::sync::mpsc; +use jsonrpc_core::futures::{Sink, Future, BoxFuture}; +use jsonrpc_core::{self as core, MetaIoHandler}; + +use v1::metadata::Metadata; + +#[derive(Debug)] +struct Subscription { + metadata: Metadata, + method: String, + params: core::Params, + sink: mpsc::Sender>, + last_result: Arc>>, +} + +/// A struct managing all subscriptions. +/// TODO [ToDr] Depending on the method decide on poll interval. +/// For most of the methods it will be enough to poll on new block instead of time-interval. +pub struct GenericPollManager> { + next_id: usize, + poll_subscriptions: HashMap, + rpc: MetaIoHandler, +} + +impl> GenericPollManager { + /// Creates new poll manager + pub fn new(rpc: MetaIoHandler) -> Self { + GenericPollManager { + next_id: 1, + poll_subscriptions: Default::default(), + rpc: rpc, + } + } + + /// Subscribes to update from polling given method. + pub fn subscribe(&mut self, metadata: Metadata, method: String, params: core::Params) + -> (usize, mpsc::Receiver>) + { + let id = self.next_id; + self.next_id += 1; + + let (sink, stream) = mpsc::channel(1); + + let subscription = Subscription { + metadata: metadata, + method: method, + params: params, + sink: sink, + last_result: Default::default(), + }; + + debug!(target: "pubsub", "Adding subscription id={:?}, {:?}", id, subscription); + self.poll_subscriptions.insert(id, subscription); + (id, stream) + } + + pub fn unsubscribe(&mut self, id: usize) -> bool { + debug!(target: "pubsub", "Removing subscription: {:?}", id); + self.poll_subscriptions.remove(&id).is_some() + } + + pub fn tick(&self) -> BoxFuture<(), ()> { + let mut futures = Vec::new(); + // poll all subscriptions + for (id, subscription) in self.poll_subscriptions.iter() { + let call = core::MethodCall { + jsonrpc: Some(core::Version::V2), + id: core::Id::Num(*id as u64), + method: subscription.method.clone(), + params: Some(subscription.params.clone()), + }; + trace!(target: "pubsub", "Polling method: {:?}", call); + let result = self.rpc.handle_call(call.into(), subscription.metadata.clone()); + + let last_result = subscription.last_result.clone(); + let sender = subscription.sink.clone(); + + let result = result.and_then(move |response| { + let mut last_result = last_result.lock(); + if *last_result != response && response.is_some() { + let output = response.expect("Existence proved by the condition."); + debug!(target: "pubsub", "Got new response, sending: {:?}", output); + *last_result = Some(output.clone()); + + let send = match output { + core::Output::Success(core::Success { result, .. }) => Ok(result), + core::Output::Failure(core::Failure { error, .. }) => Err(error), + }; + Either::A(sender.send(send).map(|_| ()).map_err(|_| ())) + } else { + trace!(target: "pubsub", "Response was not changed: {:?}", response); + Either::B(future::ok(())) + } + }); + + futures.push(result) + } + + // return a future represeting all the polls + future::join_all(futures).map(|_| ()).boxed() + } +} + +#[cfg(test)] +mod tests { + use std::sync::atomic::{self, AtomicBool}; + + use jsonrpc_core::{MetaIoHandler, NoopMiddleware, Value, Params}; + use jsonrpc_core::futures::{Future, Stream}; + use http::tokio_core::reactor; + + use super::GenericPollManager; + + fn poll_manager() -> GenericPollManager { + let mut io = MetaIoHandler::default(); + let called = AtomicBool::new(false); + io.add_method("hello", move |_| { + if !called.load(atomic::Ordering::SeqCst) { + called.store(true, atomic::Ordering::SeqCst); + Ok(Value::String("hello".into())) + } else { + Ok(Value::String("world".into())) + } + }); + GenericPollManager::new(io) + } + + #[test] + fn should_poll_subscribed_method() { + // given + let mut el = reactor::Core::new().unwrap(); + let mut poll_manager = poll_manager(); + let (id, rx) = poll_manager.subscribe(Default::default(), "hello".into(), Params::None); + assert_eq!(id, 1); + + // then + poll_manager.tick().wait().unwrap(); + let (res, rx) = el.run(rx.into_future()).unwrap(); + assert_eq!(res, Some(Ok(Value::String("hello".into())))); + + // retrieve second item + poll_manager.tick().wait().unwrap(); + let (res, rx) = el.run(rx.into_future()).unwrap(); + assert_eq!(res, Some(Ok(Value::String("world".into())))); + + // and no more notifications + poll_manager.tick().wait().unwrap(); + // we need to unsubscribe otherwise the future will never finish. + poll_manager.unsubscribe(1); + assert_eq!(el.run(rx.into_future()).unwrap().0, None); + } +} diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index cacf33db5..63e1c64b6 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -27,13 +27,14 @@ use ethkey::{Brain, Generator}; use ethstore::random_phrase; use ethsync::LightSyncProvider; use ethcore::account_provider::AccountProvider; +use crypto::DEFAULT_MAC; use light::client::LightChainClient; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings}; -use v1::helpers::dispatch::{LightDispatcher, DEFAULT_MAC}; +use v1::helpers::dispatch::LightDispatcher; use v1::helpers::light_fetch::LightFetch; use v1::metadata::Metadata; use v1::traits::Parity; diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index f5149d721..a8691b32b 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -23,16 +23,17 @@ mod parity; mod parity_accounts; mod parity_set; mod personal; +mod pubsub; mod signer; mod signing; mod signing_unsafe; mod rpc; +mod secretstore; mod traces; mod web3; pub mod light; -pub use self::web3::Web3Client; pub use self::eth::{EthClient, EthClientOptions}; pub use self::eth_filter::EthFilterClient; pub use self::net::NetClient; @@ -40,8 +41,11 @@ pub use self::parity::ParityClient; pub use self::parity_accounts::ParityAccountsClient; pub use self::parity_set::ParitySetClient; pub use self::personal::PersonalClient; +pub use self::pubsub::PubSubClient; pub use self::signer::SignerClient; pub use self::signing::SigningQueueClient; pub use self::signing_unsafe::SigningUnsafeClient; pub use self::traces::TracesClient; +pub use self::web3::Web3Client; pub use self::rpc::RpcClient; +pub use self::secretstore::SecretStoreClient; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 1b62b7f81..689ba3e70 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -34,12 +34,12 @@ use ethcore::client::{MiningBlockChainClient}; use ethcore::mode::Mode; use ethcore::account_provider::AccountProvider; use updater::{Service as UpdateService}; +use crypto::DEFAULT_MAC; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::accounts::unwrap_provider; -use v1::helpers::dispatch::DEFAULT_MAC; use v1::metadata::Metadata; use v1::traits::Parity; use v1::types::{ diff --git a/rpc/src/v1/impls/pubsub.rs b/rpc/src/v1/impls/pubsub.rs new file mode 100644 index 000000000..8badefdb8 --- /dev/null +++ b/rpc/src/v1/impls/pubsub.rs @@ -0,0 +1,100 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Parity-specific PUB-SUB rpc implementation. + +use std::sync::Arc; +use std::time::Duration; +use util::RwLock; + +use futures::{self, BoxFuture, Future, Stream, Sink}; +use jsonrpc_core::{self as core, Error, MetaIoHandler}; +use jsonrpc_macros::pubsub::Subscriber; +use jsonrpc_pubsub::SubscriptionId; +use tokio_timer; + +use parity_reactor::Remote; +use v1::helpers::GenericPollManager; +use v1::metadata::Metadata; +use v1::traits::PubSub; + +/// Parity PubSub implementation. +pub struct PubSubClient> { + poll_manager: Arc>>, + remote: Remote, +} + +impl> PubSubClient { + /// Creates new `PubSubClient`. + pub fn new(rpc: MetaIoHandler, remote: Remote) -> Self { + let poll_manager = Arc::new(RwLock::new(GenericPollManager::new(rpc))); + let pm2 = poll_manager.clone(); + + let timer = tokio_timer::wheel() + .tick_duration(Duration::from_millis(500)) + .build(); + + // Start ticking + let interval = timer.interval(Duration::from_millis(1000)); + remote.spawn(interval + .map_err(|e| warn!("Polling timer error: {:?}", e)) + .for_each(move |_| pm2.read().tick()) + ); + + PubSubClient { + poll_manager: poll_manager, + remote: remote, + } + } +} + +impl> PubSub for PubSubClient { + type Metadata = Metadata; + + fn parity_subscribe(&self, mut meta: Metadata, subscriber: Subscriber, method: String, params: core::Params) { + // Make sure to get rid of PubSub session otherwise it will never be dropped. + meta.session = None; + + let mut poll_manager = self.poll_manager.write(); + let (id, receiver) = poll_manager.subscribe(meta, method, params); + match subscriber.assign_id(SubscriptionId::Number(id as u64)) { + Ok(sink) => { + self.remote.spawn(receiver.map(|res| match res { + Ok(val) => val, + Err(error) => { + warn!(target: "pubsub", "Subscription error: {:?}", error); + core::Value::Null + }, + }).forward(sink.sink_map_err(|e| { + warn!("Cannot send notification: {:?}", e); + })).map(|_| ())); + }, + Err(_) => { + poll_manager.unsubscribe(id); + }, + } + } + + fn parity_unsubscribe(&self, id: SubscriptionId) -> BoxFuture { + let res = if let SubscriptionId::Number(id) = id { + self.poll_manager.write().unsubscribe(id as usize) + } else { + false + }; + + futures::future::ok(res).boxed() + } +} diff --git a/rpc/src/v1/impls/secretstore.rs b/rpc/src/v1/impls/secretstore.rs new file mode 100644 index 000000000..bf09baeb6 --- /dev/null +++ b/rpc/src/v1/impls/secretstore.rs @@ -0,0 +1,85 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! SecretStore-specific rpc implementation. + +use std::sync::{Arc, Weak}; + +use crypto::DEFAULT_MAC; +use ethkey::Secret; +use ethcore::account_provider::AccountProvider; + +use jsonrpc_core::Error; +use v1::helpers::errors; +use v1::helpers::accounts::unwrap_provider; +use v1::helpers::secretstore::{encrypt_document, decrypt_document, decrypt_document_with_shadow}; +use v1::traits::SecretStore; +use v1::types::{H160, H512, Bytes}; + +/// Parity implementation. +pub struct SecretStoreClient { + accounts: Option>, +} + +impl SecretStoreClient { + /// Creates new SecretStoreClient + pub fn new(store: &Option>) -> Self { + SecretStoreClient { + accounts: store.as_ref().map(Arc::downgrade), + } + } + + /// Attempt to get the `Arc`, errors if provider was not + /// set, or if upgrading the weak reference failed. + fn account_provider(&self) -> Result, Error> { + unwrap_provider(&self.accounts) + } + + /// Decrypt public key using account' private key + fn decrypt_key(&self, address: H160, password: String, key: Bytes) -> Result, Error> { + let store = self.account_provider()?; + store.decrypt(address.into(), Some(password), &DEFAULT_MAC, &key.0) + .map_err(|e| errors::account("Could not decrypt key.", e)) + } + + /// Decrypt secret key using account' private key + fn decrypt_secret(&self, address: H160, password: String, key: Bytes) -> Result { + self.decrypt_key(address, password, key) + .and_then(|s| Secret::from_slice(&s).map_err(|e| errors::account("invalid secret", e))) + } +} + +impl SecretStore for SecretStoreClient { + fn encrypt(&self, address: H160, password: String, key: Bytes, data: Bytes) -> Result { + encrypt_document(self.decrypt_key(address, password, key)?, data.0) + .map(Into::into) + } + + fn decrypt(&self, address: H160, password: String, key: Bytes, data: Bytes) -> Result { + decrypt_document(self.decrypt_key(address, password, key)?, data.0) + .map(Into::into) + } + + fn shadow_decrypt(&self, address: H160, password: String, decrypted_secret: H512, common_point: H512, decrypt_shadows: Vec, data: Bytes) -> Result { + let mut shadows = Vec::with_capacity(decrypt_shadows.len()); + for decrypt_shadow in decrypt_shadows { + shadows.push(self.decrypt_secret(address.clone(), password.clone(), decrypt_shadow)?); + } + + decrypt_document_with_shadow(decrypted_secret.into(), common_point.into(), shadows, data.0) + .map(Into::into) + } +} diff --git a/rpc/src/v1/metadata.rs b/rpc/src/v1/metadata.rs index 26c79d976..74567d510 100644 --- a/rpc/src/v1/metadata.rs +++ b/rpc/src/v1/metadata.rs @@ -14,20 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::sync::Arc; + use jsonrpc_core; +use jsonrpc_pubsub::{Session, PubSubMetadata}; use v1::types::{DappId, Origin}; /// RPC methods metadata. -#[derive(Clone, Default, Debug, PartialEq)] +#[derive(Clone, Default, Debug)] pub struct Metadata { /// Request origin pub origin: Origin, + /// Request PubSub Session + pub session: Option>, } impl Metadata { - /// Get + /// Returns dapp id if this request is coming from a Dapp or default `DappId` otherwise. pub fn dapp_id(&self) -> DappId { + // TODO [ToDr] Extract dapp info from Ws connections. match self.origin { Origin::Dapps(ref dapp_id) => dapp_id.clone(), _ => DappId::default(), @@ -36,4 +42,8 @@ impl Metadata { } impl jsonrpc_core::Metadata for Metadata {} - +impl PubSubMetadata for Metadata { + fn session(&self) -> Option> { + self.session.clone() + } +} diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index bd0656219..59aef84b3 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -58,7 +58,7 @@ pub mod traits; pub mod tests; pub mod types; -pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc}; +pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, PubSub, Signer, Personal, Traces, Rpc, SecretStore}; pub use self::impls::*; pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import, informant, dispatch}; pub use self::metadata::Metadata; diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index aec2021a1..e5a459633 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -24,7 +24,9 @@ mod parity; mod parity_accounts; mod parity_set; mod personal; +mod pubsub; mod rpc; +mod secretstore; mod signer; mod signing; mod traces; diff --git a/rpc/src/v1/tests/mocked/pubsub.rs b/rpc/src/v1/tests/mocked/pubsub.rs new file mode 100644 index 000000000..b7c8963e5 --- /dev/null +++ b/rpc/src/v1/tests/mocked/pubsub.rs @@ -0,0 +1,76 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::{atomic, Arc}; + +use jsonrpc_core::{self as core, MetaIoHandler}; +use jsonrpc_core::futures::{self, Stream, Future}; +use jsonrpc_pubsub::Session; + +use parity_reactor::EventLoop; +use v1::{PubSub, PubSubClient, Metadata}; + +fn rpc() -> MetaIoHandler { + let mut io = MetaIoHandler::default(); + let called = atomic::AtomicBool::new(false); + io.add_method("hello", move |_| { + if !called.load(atomic::Ordering::SeqCst) { + called.store(true, atomic::Ordering::SeqCst); + Ok(core::Value::String("hello".into())) + } else { + Ok(core::Value::String("world".into())) + } + }); + io +} + +#[test] +fn should_subscribe_to_a_method() { + // given + let el = EventLoop::spawn(); + let rpc = rpc(); + let pubsub = PubSubClient::new(rpc, el.remote()).to_delegate(); + + let mut io = MetaIoHandler::default(); + io.extend_with(pubsub); + + let mut metadata = Metadata::default(); + let (sender, receiver) = futures::sync::mpsc::channel(8); + metadata.session = Some(Arc::new(Session::new(sender))); + + // Subscribe + let request = r#"{"jsonrpc": "2.0", "method": "parity_subscribe", "params": ["hello", []], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":1,"id":1}"#; + assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned())); + + // Check notifications + let (res, receiver) = receiver.into_future().wait().unwrap(); + let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"hello","subscription":1}}"#; + assert_eq!(res, Some(response.into())); + + let (res, receiver) = receiver.into_future().wait().unwrap(); + let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"world","subscription":1}}"#; + assert_eq!(res, Some(response.into())); + + // And unsubscribe + let request = r#"{"jsonrpc": "2.0", "method": "parity_unsubscribe", "params": [1], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + assert_eq!(io.handle_request_sync(request, metadata), Some(response.to_owned())); + + let (res, _receiver) = receiver.into_future().wait().unwrap(); + assert_eq!(res, None); +} + diff --git a/rpc/src/v1/tests/mocked/secretstore.rs b/rpc/src/v1/tests/mocked/secretstore.rs new file mode 100644 index 000000000..ed278ced8 --- /dev/null +++ b/rpc/src/v1/tests/mocked/secretstore.rs @@ -0,0 +1,98 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::Arc; + +use ethcore::account_provider::AccountProvider; + +use serde_json; +use jsonrpc_core::{IoHandler, Success}; +use v1::metadata::Metadata; +use v1::SecretStoreClient; +use v1::traits::secretstore::SecretStore; + +struct Dependencies { + pub accounts: Arc, +} + +impl Dependencies { + pub fn new() -> Self { + Dependencies { + accounts: Arc::new(AccountProvider::transient_provider()), + } + } + + pub fn client(&self) -> SecretStoreClient { + SecretStoreClient::new(&Some(self.accounts.clone())) + } + + fn default_client(&self) -> IoHandler { + let mut io = IoHandler::default(); + io.extend_with(self.client().to_delegate()); + io + } +} + +#[test] +fn rpc_secretstore_encrypt_and_decrypt() { + let deps = Dependencies::new(); + let io = deps.default_client(); + + // insert new account && unlock it + let secret = "c1f1cfe279a5c350d13795bce162941967340c8a228e6ba175489afc564a5bef".parse().unwrap(); + deps.accounts.insert_account(secret, "password").unwrap(); + + // execute encryption request + let encryption_request = r#"{"jsonrpc": "2.0", "method": "secretstore_encrypt", "params":[ + "0x5c2f3b4ec0c2234f8358697edc8b82a62e3ac995", "password", + "0x0440262acc06f1e13cb11b34e792cdf698673a16bb812163cb52689ac34c94ae47047b58f58d8b596d21ac7b03a55896132d07a7dc028b2dad88f6c5a90623fa5b30ff4b1ba385a98c970432d13417cf6d7facd62f86faaef15ca993735890da0cb3e417e2740fc72de7501eef083a12dd5a9ebe513b592b1740848576a936a1eb88fc553fc624b1cae41a0a4e074e34e2aaae686709f08d70e505c5acba12ef96017e89be675a2adb07c72c4e95814fbf", + "0xdeadbeef" + ], "id": 1}"#; + let encryption_response = io.handle_request_sync(encryption_request).unwrap(); + let encryption_response: Success = serde_json::from_str(&encryption_response).unwrap(); + + // execute decryption request + let decryption_request_left = r#"{"jsonrpc": "2.0", "method": "secretstore_decrypt", "params":[ + "0x5c2f3b4ec0c2234f8358697edc8b82a62e3ac995", "password", + "0x0440262acc06f1e13cb11b34e792cdf698673a16bb812163cb52689ac34c94ae47047b58f58d8b596d21ac7b03a55896132d07a7dc028b2dad88f6c5a90623fa5b30ff4b1ba385a98c970432d13417cf6d7facd62f86faaef15ca993735890da0cb3e417e2740fc72de7501eef083a12dd5a9ebe513b592b1740848576a936a1eb88fc553fc624b1cae41a0a4e074e34e2aaae686709f08d70e505c5acba12ef96017e89be675a2adb07c72c4e95814fbf",""#; + let decryption_request_mid = encryption_response.result.as_str().unwrap(); + let decryption_request_right = r#"" + ], "id": 2}"#; + let decryption_request = decryption_request_left.to_owned() + decryption_request_mid + decryption_request_right; + let decryption_response = io.handle_request_sync(&decryption_request).unwrap(); + assert_eq!(decryption_response, r#"{"jsonrpc":"2.0","result":"0xdeadbeef","id":2}"#); +} + +#[test] +fn rpc_secretstore_shadow_decrypt() { + let deps = Dependencies::new(); + let io = deps.default_client(); + + // insert new account && unlock it + let secret = "82758356bf46b42710d3946a8efa612b7bf5e125e4d49f28facf1139db4a46f4".parse().unwrap(); + deps.accounts.insert_account(secret, "password").unwrap(); + + // execute decryption request + let decryption_request = r#"{"jsonrpc": "2.0", "method": "secretstore_shadowDecrypt", "params":[ + "0x00dfE63B22312ab4329aD0d28CaD8Af987A01932", "password", + "0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91", + "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3", + ["0x049ce50bbadb6352574f2c59742f78df83333975cbd5cbb151c6e8628749a33dc1fa93bb6dffae5994e3eb98ae859ed55ee82937538e6adb054d780d1e89ff140f121529eeadb1161562af9d3342db0008919ca280a064305e5a4e518e93279de7a9396fe5136a9658e337e8e276221248c381c5384cd1ad28e5921f46ff058d5fbcf8a388fc881d0dd29421c218d51761"], + "0x2ddec1f96229efa2916988d8b2a82a47ef36f71c" + ], "id": 1}"#; + let decryption_response = io.handle_request_sync(&decryption_request).unwrap(); + assert_eq!(decryption_response, r#"{"jsonrpc":"2.0","result":"0xdeadbeef","id":1}"#); +} diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index 6279ca0b4..9cef58ee7 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -25,9 +25,11 @@ pub mod parity_accounts; pub mod parity_set; pub mod parity_signing; pub mod personal; +pub mod pubsub; pub mod signer; pub mod traces; pub mod rpc; +pub mod secretstore; pub use self::web3::Web3; pub use self::eth::{Eth, EthFilter}; @@ -38,7 +40,8 @@ pub use self::parity_accounts::ParityAccounts; pub use self::parity_set::ParitySet; pub use self::parity_signing::ParitySigning; pub use self::personal::Personal; +pub use self::pubsub::PubSub; pub use self::signer::Signer; pub use self::traces::Traces; pub use self::rpc::Rpc; - +pub use self::secretstore::SecretStore; diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index a0a8cf1a4..f62f5ce7b 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -43,7 +43,7 @@ build_rpc_trait! { #[rpc(meta, name = "personal_sendTransaction")] fn send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; - /// Deprecated alias for `personal_sendTransaction`. + /// @deprecated alias for `personal_sendTransaction`. #[rpc(meta, name = "personal_signAndSendTransaction")] fn sign_and_send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; diff --git a/rpc/src/v1/traits/pubsub.rs b/rpc/src/v1/traits/pubsub.rs new file mode 100644 index 000000000..a4672403a --- /dev/null +++ b/rpc/src/v1/traits/pubsub.rs @@ -0,0 +1,39 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Parity-specific PUB-SUB rpc interface. + +use jsonrpc_core::{Error, Value, Params}; +use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_macros::pubsub::Subscriber; +use futures::BoxFuture; + +build_rpc_trait! { + /// Parity-specific PUB-SUB rpc interface. + pub trait PubSub { + type Metadata; + + #[pubsub(name = "parity_subscription")] { + /// Subscribe to changes of any RPC method in Parity. + #[rpc(name = "parity_subscribe")] + fn parity_subscribe(&self, Self::Metadata, Subscriber, String, Params); + + /// Unsubscribe from existing Parity subscription. + #[rpc(name = "parity_unsubscribe")] + fn parity_unsubscribe(&self, SubscriptionId) -> BoxFuture; + } + } +} diff --git a/rpc/src/v1/traits/secretstore.rs b/rpc/src/v1/traits/secretstore.rs new file mode 100644 index 000000000..c13367562 --- /dev/null +++ b/rpc/src/v1/traits/secretstore.rs @@ -0,0 +1,41 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! SecretStore-specific rpc interface. + +use jsonrpc_core::Error; + +use v1::types::{H160, H512, Bytes}; + +build_rpc_trait! { + /// Parity-specific rpc interface. + pub trait SecretStore { + /// Encrypt data with key, received from secret store. + /// Arguments: `account`, `password`, `key`, `data`. + #[rpc(name = "secretstore_encrypt")] + fn encrypt(&self, H160, String, Bytes, Bytes) -> Result; + + /// Decrypt data with key, received from secret store. + /// Arguments: `account`, `password`, `key`, `data`. + #[rpc(name = "secretstore_decrypt")] + fn decrypt(&self, H160, String, Bytes, Bytes) -> Result; + + /// Decrypt data with shadow key, received from secret store. + /// Arguments: `account`, `password`, `decrypted_secret`, `common_point`, `decrypt_shadows`, `data`. + #[rpc(name = "secretstore_shadowDecrypt")] + fn shadow_decrypt(&self, H160, String, H512, H512, Vec, Bytes) -> Result; + } +} diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh index 70bc85912..c83912080 100644 --- a/scripts/docker-build.sh +++ b/scripts/docker-build.sh @@ -1,4 +1,5 @@ #!/bin/bash cd docker/hub if [ "$1" == "latest" ]; then DOCKER_BUILD_TAG="beta-release"; fi -docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag ethcore/parity:$1 . +docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag $2/parity:$1 . +docker push $2/parity:$1 diff --git a/secret_store/src/http_listener.rs b/secret_store/src/http_listener.rs index 482fa92f6..bc51811de 100644 --- a/secret_store/src/http_listener.rs +++ b/secret_store/src/http_listener.rs @@ -24,9 +24,8 @@ use hyper::server::{Server as HttpServer, Request as HttpRequest, Response as Ht use serde_json; use url::percent_encoding::percent_decode; -use util::ToPretty; use traits::KeyServer; -use serialization::SerializableDocumentEncryptedKeyShadow; +use serialization::{SerializableDocumentEncryptedKeyShadow, SerializableBytes}; use types::all::{Error, NodeAddress, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow}; /// Key server http-requests listener @@ -168,9 +167,10 @@ impl HttpHandler for KeyServerHttpHandler where T: KeyServer + 'static { } fn return_document_key(req: HttpRequest, mut res: HttpResponse, document_key: Result) { + let document_key = document_key. + and_then(|k| serde_json::to_vec(&SerializableBytes(k)).map_err(|e| Error::Serde(e.to_string()))); match document_key { Ok(document_key) => { - let document_key = document_key.to_hex().into_bytes(); res.headers_mut().set(header::ContentType::plaintext()); if let Err(err) = res.send(&document_key) { // nothing to do, but to log an error @@ -186,6 +186,7 @@ fn return_error(mut res: HttpResponse, err: Error) { Error::BadSignature => *res.status_mut() = HttpStatusCode::BadRequest, Error::AccessDenied => *res.status_mut() = HttpStatusCode::Forbidden, Error::DocumentNotFound => *res.status_mut() = HttpStatusCode::NotFound, + Error::Serde(_) => *res.status_mut() = HttpStatusCode::BadRequest, Error::Database(_) => *res.status_mut() = HttpStatusCode::InternalServerError, Error::Internal(_) => *res.status_mut() = HttpStatusCode::InternalServerError, } diff --git a/secret_store/src/key_server.rs b/secret_store/src/key_server.rs index 49016ac8e..f960c5cc5 100644 --- a/secret_store/src/key_server.rs +++ b/secret_store/src/key_server.rs @@ -67,7 +67,7 @@ impl KeyServer for KeyServerImpl { let document_key = encryption_session.wait(None)?; // encrypt document key with requestor public key - let document_key = ethcrypto::ecies::encrypt_single_message(&public, &document_key) + let document_key = ethcrypto::ecies::encrypt(&public, ðcrypto::DEFAULT_MAC, &document_key) .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; Ok(document_key) } @@ -83,13 +83,13 @@ impl KeyServer for KeyServerImpl { let document_key = decryption_session.wait()?.decrypted_secret; // encrypt document key with requestor public key - let document_key = ethcrypto::ecies::encrypt_single_message(&public, &document_key) + let document_key = ethcrypto::ecies::encrypt(&public, ðcrypto::DEFAULT_MAC, &document_key) .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; Ok(document_key) } fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result { - let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), false)?; + let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), true)?; decryption_session.wait().map_err(Into::into) } } @@ -118,7 +118,7 @@ impl KeyServerCore { return; }, }; - + let cluster = ClusterCore::new(el.handle(), config); let cluster_client = cluster.and_then(|c| c.run().map(|_| c.client())); tx.send(cluster_client.map_err(Into::into)).expect("Rx is blocking upper thread."); @@ -229,12 +229,12 @@ pub mod tests { let secret = Random.generate().unwrap().secret().clone(); let signature = ethkey::sign(&secret, &document).unwrap(); let generated_key = key_servers[0].generate_document_key(&signature, &document, threshold).unwrap(); - let generated_key = ethcrypto::ecies::decrypt_single_message(&secret, &generated_key).unwrap(); + let generated_key = ethcrypto::ecies::decrypt(&secret, ðcrypto::DEFAULT_MAC, &generated_key).unwrap(); // now let's try to retrieve key back for key_server in key_servers.iter() { let retrieved_key = key_server.document_key(&signature, &document).unwrap(); - let retrieved_key = ethcrypto::ecies::decrypt_single_message(&secret, &retrieved_key).unwrap(); + let retrieved_key = ethcrypto::ecies::decrypt(&secret, ðcrypto::DEFAULT_MAC, &retrieved_key).unwrap(); assert_eq!(retrieved_key, generated_key); } } @@ -251,12 +251,12 @@ pub mod tests { let secret = Random.generate().unwrap().secret().clone(); let signature = ethkey::sign(&secret, &document).unwrap(); let generated_key = key_servers[0].generate_document_key(&signature, &document, *threshold).unwrap(); - let generated_key = ethcrypto::ecies::decrypt_single_message(&secret, &generated_key).unwrap(); + let generated_key = ethcrypto::ecies::decrypt(&secret, ðcrypto::DEFAULT_MAC, &generated_key).unwrap(); // now let's try to retrieve key back for key_server in key_servers.iter() { let retrieved_key = key_server.document_key(&signature, &document).unwrap(); - let retrieved_key = ethcrypto::ecies::decrypt_single_message(&secret, &retrieved_key).unwrap(); + let retrieved_key = ethcrypto::ecies::decrypt(&secret, ðcrypto::DEFAULT_MAC, &retrieved_key).unwrap(); assert_eq!(retrieved_key, generated_key); } } diff --git a/secret_store/src/key_server_cluster/decryption_session.rs b/secret_store/src/key_server_cluster/decryption_session.rs index f4d64c246..8f5ecff7d 100644 --- a/secret_store/src/key_server_cluster/decryption_session.rs +++ b/secret_store/src/key_server_cluster/decryption_session.rs @@ -18,7 +18,8 @@ use std::cmp::{Ord, PartialOrd, Ordering}; use std::collections::{BTreeSet, BTreeMap}; use std::sync::Arc; use parking_lot::{Mutex, Condvar}; -use ethcrypto::ecies::encrypt_single_message; +use ethcrypto::ecies::encrypt; +use ethcrypto::DEFAULT_MAC; use ethkey::{self, Secret, Public, Signature}; use key_server_cluster::{Error, AclStorage, DocumentKeyShare, NodeId, SessionId, DocumentEncryptedKeyShadow}; use key_server_cluster::cluster::Cluster; @@ -688,7 +689,7 @@ fn do_partial_decryption(node: &NodeId, requestor_public: &Public, is_shadow_dec shadow_point: shadow_point, decrypt_shadow: match decrypt_shadow { None => None, - Some(decrypt_shadow) => Some(encrypt_single_message(requestor_public, &**decrypt_shadow)?), + Some(decrypt_shadow) => Some(encrypt(requestor_public, &DEFAULT_MAC, &**decrypt_shadow)?), }, }) } @@ -1085,9 +1086,10 @@ mod tests { assert!(decrypted_secret.common_point.is_some()); assert!(decrypted_secret.decrypt_shadows.is_some()); // check that KS client is able to restore original secret - use ethcrypto::ecies::decrypt_single_message; + use ethcrypto::DEFAULT_MAC; + use ethcrypto::ecies::decrypt; let decrypt_shadows: Vec<_> = decrypted_secret.decrypt_shadows.unwrap().into_iter() - .map(|c| Secret::from_slice(&decrypt_single_message(key_pair.secret(), &c).unwrap()).unwrap()) + .map(|c| Secret::from_slice(&decrypt(key_pair.secret(), &DEFAULT_MAC, &c).unwrap()).unwrap()) .collect(); let decrypted_secret = math::decrypt_with_shadow_coefficients(decrypted_secret.decrypted_secret, decrypted_secret.common_point.unwrap(), decrypt_shadows).unwrap(); assert_eq!(decrypted_secret, SECRET_PLAIN.into()); diff --git a/secret_store/src/serialization.rs b/secret_store/src/serialization.rs index e918348fb..c88e9edf7 100644 --- a/secret_store/src/serialization.rs +++ b/secret_store/src/serialization.rs @@ -34,9 +34,9 @@ pub struct SerializableDocumentEncryptedKeyShadow { pub decrypt_shadows: Vec, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// Serializable Bytes. -pub struct SerializableBytes(Bytes); +pub struct SerializableBytes(pub Bytes); impl From for SerializableBytes where Bytes: From { fn from(s: T) -> SerializableBytes { @@ -60,7 +60,9 @@ impl Deref for SerializableBytes { impl Serialize for SerializableBytes { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&(*self.0).to_hex()) + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) } } @@ -69,14 +71,18 @@ impl Deserialize for SerializableBytes { where D: Deserializer { let s = String::deserialize(deserializer)?; - let data = s.from_hex().map_err(SerdeError::custom)?; - Ok(SerializableBytes(data)) + if s.len() >= 2 && &s[0..2] == "0x" && s.len() & 1 == 0 { + let data = s[2..].from_hex().map_err(SerdeError::custom)?; + Ok(SerializableBytes(data)) + } else { + Err(SerdeError::custom("invalid format")) + } } } #[derive(Clone, Debug)] /// Serializable Signature. -pub struct SerializableSignature(Signature); +pub struct SerializableSignature(pub Signature); impl From for SerializableSignature where Signature: From { fn from(s: T) -> SerializableSignature { @@ -100,7 +106,9 @@ impl Deref for SerializableSignature { impl Serialize for SerializableSignature { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&(*self.0).to_hex()) + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) } } @@ -116,7 +124,11 @@ impl Deserialize for SerializableSignature { } fn visit_str(self, value: &str) -> Result where E: SerdeError { - value.parse().map(|s| SerializableSignature(s)).map_err(SerdeError::custom) + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + value[2..].parse().map(|s| SerializableSignature(s)).map_err(SerdeError::custom) + } else { + Err(SerdeError::custom("invalid format")) + } } fn visit_string(self, value: String) -> Result where E: SerdeError { @@ -130,7 +142,7 @@ impl Deserialize for SerializableSignature { #[derive(Clone, Debug)] /// Serializable H256. -pub struct SerializableH256(H256); +pub struct SerializableH256(pub H256); impl From for SerializableH256 where H256: From { fn from(s: T) -> SerializableH256 { @@ -154,7 +166,9 @@ impl Deref for SerializableH256 { impl Serialize for SerializableH256 { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&(*self.0).to_hex()) + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) } } @@ -170,7 +184,11 @@ impl Deserialize for SerializableH256 { } fn visit_str(self, value: &str) -> Result where E: SerdeError { - value.parse().map(|s| SerializableH256(s)).map_err(SerdeError::custom) + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + value[2..].parse().map(|s| SerializableH256(s)).map_err(SerdeError::custom) + } else { + Err(SerdeError::custom("invalid format")) + } } fn visit_string(self, value: String) -> Result where E: SerdeError { @@ -184,7 +202,7 @@ impl Deserialize for SerializableH256 { #[derive(Clone, Debug)] /// Serializable EC scalar/secret key. -pub struct SerializableSecret(Secret); +pub struct SerializableSecret(pub Secret); impl From for SerializableSecret where Secret: From { fn from(s: T) -> SerializableSecret { @@ -208,7 +226,9 @@ impl Deref for SerializableSecret { impl Serialize for SerializableSecret { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&(*self.0).to_hex()) + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) } } @@ -224,7 +244,11 @@ impl Deserialize for SerializableSecret { } fn visit_str(self, value: &str) -> Result where E: SerdeError { - value.parse().map(|s| SerializableSecret(s)).map_err(SerdeError::custom) + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + value[2..].parse().map(|s| SerializableSecret(s)).map_err(SerdeError::custom) + } else { + Err(SerdeError::custom("invalid format")) + } } fn visit_string(self, value: String) -> Result where E: SerdeError { @@ -238,7 +262,7 @@ impl Deserialize for SerializableSecret { #[derive(Clone, Debug)] /// Serializable EC point/public key. -pub struct SerializablePublic(Public); +pub struct SerializablePublic(pub Public); impl From for SerializablePublic where Public: From { fn from(p: T) -> SerializablePublic { @@ -282,7 +306,9 @@ impl PartialOrd for SerializablePublic { impl Serialize for SerializablePublic { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&(*self.0).to_hex()) + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) } } @@ -298,7 +324,11 @@ impl Deserialize for SerializablePublic { } fn visit_str(self, value: &str) -> Result where E: SerdeError { - value.parse().map(|s| SerializablePublic(s)).map_err(SerdeError::custom) + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + value[2..].parse().map(|s| SerializablePublic(s)).map_err(SerdeError::custom) + } else { + Err(SerdeError::custom("invalid format")) + } } fn visit_string(self, value: String) -> Result where E: SerdeError { @@ -309,3 +339,27 @@ impl Deserialize for SerializablePublic { deserializer.deserialize(HashVisitor) } } + +#[cfg(test)] +mod tests { + use serde_json; + use super::{SerializableBytes, SerializablePublic}; + + #[test] + fn serialize_and_deserialize_bytes() { + let bytes = SerializableBytes(vec![1, 2, 3, 4]); + let bytes_serialized = serde_json::to_string(&bytes).unwrap(); + assert_eq!(&bytes_serialized, r#""0x01020304""#); + let bytes_deserialized: SerializableBytes = serde_json::from_str(&bytes_serialized).unwrap(); + assert_eq!(bytes_deserialized, bytes); + } + + #[test] + fn serialize_and_deserialize_public() { + let public = SerializablePublic("cac6c205eb06c8308d65156ff6c862c62b000b8ead121a4455a8ddeff7248128d895692136f240d5d1614dc7cc4147b1bd584bd617e30560bb872064d09ea325".parse().unwrap()); + let public_serialized = serde_json::to_string(&public).unwrap(); + assert_eq!(&public_serialized, r#""0xcac6c205eb06c8308d65156ff6c862c62b000b8ead121a4455a8ddeff7248128d895692136f240d5d1614dc7cc4147b1bd584bd617e30560bb872064d09ea325""#); + let public_deserialized: SerializablePublic = serde_json::from_str(&public_serialized).unwrap(); + assert_eq!(public_deserialized, public); + } +} diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index e3302a699..905841ea7 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -16,6 +16,7 @@ use std::fmt; use std::collections::BTreeMap; +use serde_json; use ethkey; use util; @@ -44,6 +45,8 @@ pub enum Error { AccessDenied, /// Requested document not found DocumentNotFound, + /// Serialization/deserialization error + Serde(String), /// Database-related error Database(String), /// Internal error @@ -107,12 +110,19 @@ impl fmt::Display for Error { Error::BadSignature => write!(f, "Bad signature"), Error::AccessDenied => write!(f, "Access dened"), Error::DocumentNotFound => write!(f, "Document not found"), + Error::Serde(ref msg) => write!(f, "Serialization error: {}", msg), Error::Database(ref msg) => write!(f, "Database error: {}", msg), Error::Internal(ref msg) => write!(f, "Internal error: {}", msg), } } } +impl From for Error { + fn from(err: serde_json::Error) -> Self { + Error::Serde(err.to_string()) + } +} + impl From for Error { fn from(err: ethkey::Error) -> Self { Error::Internal(err.into())