diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2460678d4..d27b58f9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -108,9 +108,9 @@ linux-centos: paths: - target/release/parity name: "x86_64-unknown-centos-gnu_parity" -linux-i686: - stage: build - image: ethcore/rust-i686:latest +linux-i686: + stage: build + image: ethcore/rust-i686:latest only: - beta - tags @@ -348,7 +348,7 @@ windows: - set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include;C:\vs2015\VC\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt - set LIB=C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64 - set RUST_BACKTRACE=1 - - set RUSTFLAGS=%RUSTFLAGS% + - set RUSTFLAGS=%RUSTFLAGS% - rustup default stable-x86_64-pc-windows-msvc - cargo build -j 8 --release #%CARGOFLAGS% - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll @@ -422,13 +422,14 @@ test-rust-stable: image: ethcore/rust:stable before_script: - git submodule update --init --recursive - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l) - - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else ./js/scripts/install-deps.sh;fi + - export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v ^js/ | wc -l) + - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) + - echo "rust/js modified: $RUST_FILES_MODIFIED / $JS_FILES_MODIFIED" + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi script: - export RUST_BACKTRACE=1 - - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"&./test.sh $CARGOFLAGS; else echo "skip rust test"&./js/scripts/lint.sh&./js/scripts/test.sh&./js/scripts/build.sh; fi + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS lint since no JS files modified."; else ./js/scripts/lint.sh && ./js/scripts/test.sh && ./js/scripts/build.sh; fi + - if [ "$RUST_FILES_MODIFIED" = 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi tags: - rust - rust-stable @@ -437,13 +438,13 @@ js-test: image: ethcore/rust:stable before_script: - git submodule update --init --recursive - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l) + - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else ./js/scripts/install-deps.sh;fi + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi script: - export RUST_BACKTRACE=1 - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else echo "skip rust test"&./js/scripts/lint.sh&./js/scripts/test.sh&./js/scripts/build.sh; fi + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS lint since no JS files modified."; else ./js/scripts/lint.sh && ./js/scripts/test.sh && ./js/scripts/build.sh; fi tags: - rust - rust-stable @@ -484,11 +485,11 @@ js-release: - stable image: ethcore/rust:stable before_script: - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l) + - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js build"; else ./js/scripts/install-deps.sh;fi + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi script: - echo $JS_FILES_MODIFIED - - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js build"; else ./js/scripts/build.sh&&./js/scripts/release.sh; fi + - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "Skipping JS rebuild since no JS files modified."; else ./js/scripts/build.sh && ./js/scripts/release.sh; fi tags: - javascript diff --git a/Cargo.lock b/Cargo.lock index adc9a41d4..7e970051c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,7 @@ dependencies = [ "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.5.0", + "ethcore-devtools 1.5.0", "ethcore-io 1.5.0", "ethcore-ipc 1.5.0", "ethcore-ipc-codegen 1.5.0", @@ -683,6 +684,7 @@ dependencies = [ "ethcore-light 1.5.0", "ethcore-network 1.5.0", "ethcore-util 1.5.0", + "ethkey 0.2.0", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1288,7 +1290,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#f5365b857b006ed60c02eb9360d60d7ddef65104" +source = "git+https://github.com/ethcore/js-precompiled.git#3d3b2f9e8e8b0fd62c172240bfd001a317cf2979" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/res/authority_round.json b/ethcore/res/authority_round.json index a0f88b85b..85beb51b4 100644 --- a/ethcore/res/authority_round.json +++ b/ethcore/res/authority_round.json @@ -4,7 +4,8 @@ "AuthorityRound": { "params": { "gasLimitBoundDivisor": "0x0400", - "stepDuration": "1", + "stepDuration": 1, + "startStep": 2, "authorities" : [ "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e", "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 9cfad4b96..dfd899b29 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -255,6 +255,11 @@ impl Client { self.notify.write().push(Arc::downgrade(&target)); } + /// Returns engine reference. + pub fn engine(&self) -> &Engine { + &*self.engine + } + fn notify(&self, f: F) where F: Fn(&ChainNotify) { for np in self.notify.read().iter() { if let Some(n) = np.upgrade() { @@ -563,6 +568,11 @@ impl Client { results.len() } + /// Get shared miner reference. + pub fn miner(&self) -> Arc { + self.miner.clone() + } + /// Used by PoA to try sealing on period change. pub fn update_sealing(&self) { self.miner.update_sealing(self) @@ -1060,6 +1070,10 @@ impl BlockChainClient for Client { self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address)) } + fn transaction_block(&self, id: TransactionID) -> Option { + self.transaction_address(id).map(|addr| addr.block_hash) + } + fn uncle(&self, id: UncleID) -> Option { let index = id.position; self.block_body(id.block).and_then(|body| BodyView::new(&body).uncle_rlp_at(index)) @@ -1433,4 +1447,4 @@ mod tests { assert!(client.tree_route(&genesis, &new_hash).is_none()); } -} \ No newline at end of file +} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 37674e29e..317a481c7 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -255,7 +255,7 @@ impl TestBlockChainClient { } /// Make a bad block by setting invalid extra data. - pub fn corrupt_block(&mut self, n: BlockNumber) { + pub fn corrupt_block(&self, n: BlockNumber) { let hash = self.block_hash(BlockID::Number(n)).unwrap(); let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap()); header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec()); @@ -267,7 +267,7 @@ impl TestBlockChainClient { } /// Make a bad block by setting invalid parent hash. - pub fn corrupt_block_parent(&mut self, n: BlockNumber) { + pub fn corrupt_block_parent(&self, n: BlockNumber) { let hash = self.block_hash(BlockID::Number(n)).unwrap(); let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap()); header.set_parent_hash(H256::from(42)); @@ -432,6 +432,10 @@ impl BlockChainClient for TestBlockChainClient { None // Simple default. } + fn transaction_block(&self, _id: TransactionID) -> Option { + None // Simple default. + } + fn uncle(&self, _id: UncleID) -> Option { None // Simple default. } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 7bf17279c..e23a564d4 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -129,6 +129,9 @@ pub trait BlockChainClient : Sync + Send { /// Get transaction with given hash. fn transaction(&self, id: TransactionID) -> Option; + /// Get the hash of block that contains the transaction, if any. + fn transaction_block(&self, id: TransactionID) -> Option; + /// Get uncle with given id. fn uncle(&self, id: UncleID) -> Option; diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index f632c9382..21a6e4761 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -49,6 +49,8 @@ pub struct AuthorityRoundParams { pub authorities: Vec
, /// Number of authorities. pub authority_n: usize, + /// Starting step, + pub start_step: Option, } impl From for AuthorityRoundParams { @@ -58,6 +60,7 @@ impl From for AuthorityRoundParams { step_duration: Duration::from_secs(p.step_duration.into()), authority_n: p.authorities.len(), authorities: p.authorities.into_iter().map(Into::into).collect::>(), + start_step: p.start_step.map(Into::into), } } } @@ -97,7 +100,7 @@ impl AsMillis for Duration { impl AuthorityRound { /// Create a new instance of AuthorityRound engine. pub fn new(params: CommonParams, our_params: AuthorityRoundParams, builtins: BTreeMap) -> Result, Error> { - let initial_step = (unix_now().as_secs() / our_params.step_duration.as_secs()) as usize; + let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize; let engine = Arc::new( AuthorityRound { params: params, @@ -160,14 +163,7 @@ impl IoHandler<()> for TransitionHandler { fn timeout(&self, io: &IoContext<()>, timer: TimerToken) { if timer == ENGINE_TIMEOUT_TOKEN { if let Some(engine) = self.engine.upgrade() { - engine.step.fetch_add(1, AtomicOrdering::SeqCst); - engine.proposed.store(false, AtomicOrdering::SeqCst); - if let Some(ref channel) = *engine.message_channel.lock() { - match channel.send(ClientIoMessage::UpdateSealing) { - Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", engine.step.load(AtomicOrdering::Relaxed)), - Err(err) => trace!(target: "poa", "timeout: Could not send a sealing message {} for step {}.", err, engine.step.load(AtomicOrdering::Relaxed)), - } - } + engine.step(); io.register_timer_once(ENGINE_TIMEOUT_TOKEN, engine.remaining_step_duration().as_millis()) .unwrap_or_else(|e| warn!(target: "poa", "Failed to restart consensus step timer: {}.", e)) } @@ -184,6 +180,17 @@ impl Engine for AuthorityRound { fn params(&self) -> &CommonParams { &self.params } fn builtins(&self) -> &BTreeMap { &self.builtins } + fn step(&self) { + self.step.fetch_add(1, AtomicOrdering::SeqCst); + self.proposed.store(false, AtomicOrdering::SeqCst); + if let Some(ref channel) = *self.message_channel.lock() { + match channel.send(ClientIoMessage::UpdateSealing) { + Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", self.step.load(AtomicOrdering::Relaxed)), + Err(err) => trace!(target: "poa", "timeout: Could not send a sealing message {} for step {}.", err, self.step.load(AtomicOrdering::Relaxed)), + } + } + } + /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, header: &Header) -> BTreeMap { map![ @@ -235,6 +242,8 @@ impl Engine for AuthorityRound { } else { warn!(target: "poa", "generate_seal: FAIL: Accounts not provided."); } + } else { + trace!(target: "poa", "generate_seal: Not a proposer for step {}.", step); } None } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index d7ff06248..8e407f0b7 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -160,4 +160,6 @@ pub trait Engine : Sync + Send { /// Add an account provider useful for Engines that sign stuff. fn register_account_provider(&self, _account_provider: Arc) {} + /// Trigger next step of the consensus engine. + fn step(&self) {} } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 8d1f55567..b171856b9 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -23,7 +23,7 @@ use account_provider::{AccountProvider, Error as AccountError}; use views::{BlockView, HeaderView}; use header::Header; use state::{State, CleanupMode}; -use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics}; +use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics, TransactionID}; use client::TransactionImportResult; use executive::contract_address; use block::{ClosedBlock, SealedBlock, IsBlock, Block}; @@ -357,6 +357,8 @@ impl Miner { let block_number = open_block.block().fields().header.number(); // TODO Push new uncles too. + let mut tx_count: usize = 0; + let tx_total = transactions.len(); for tx in transactions { let hash = tx.hash(); let start = Instant::now(); @@ -378,7 +380,7 @@ impl Miner { }, _ => {}, } - + trace!(target: "miner", "Adding tx {:?} took {:?}", hash, took); match result { Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, gas })) => { debug!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?} (limit: {:?}, used: {:?}, gas: {:?})", hash, gas_limit, gas_used, gas); @@ -407,9 +409,12 @@ impl Miner { "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", block_number, hash, e); }, - _ => {} // imported ok + _ => { + tx_count += 1; + } // imported ok } } + trace!(target: "miner", "Pushed {}/{} transactions", tx_count, tx_total); let block = open_block.close(); @@ -580,6 +585,10 @@ impl Miner { let best_block_header: Header = ::rlp::decode(&chain.best_block_header()); transactions.into_iter() .map(|tx| { + if chain.transaction_block(TransactionID::Hash(tx.hash())).is_some() { + debug!(target: "miner", "Rejected tx {:?}: already in the blockchain", tx.hash()); + return Err(Error::Transaction(TransactionError::AlreadyImported)); + } match self.engine.verify_transaction_basic(&tx, &best_block_header) { Err(e) => { debug!(target: "miner", "Rejected tx {:?} with invalid signature: {:?}", tx.hash(), e); diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index c9ae087c0..e14ea3949 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -273,7 +273,7 @@ impl Spec { pub fn new_instant() -> Spec { load_bundled!("instant_seal") } /// Create a new Spec with AuthorityRound consensus which does internal sealing (not requiring work). - /// Accounts with secrets "1".sha3() and "2".sha3() are the authorities. + /// Accounts with secrets "0".sha3() and "1".sha3() are the authorities. pub fn new_test_round() -> Self { load_bundled!("authority_round") } } diff --git a/js/package.json b/js/package.json index 4cbac5a75..404a625b5 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.100", + "version": "0.2.105", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", diff --git a/js/src/3rdparty/etherscan/links.js b/js/src/3rdparty/etherscan/links.js index 2745873fc..e85572850 100644 --- a/js/src/3rdparty/etherscan/links.js +++ b/js/src/3rdparty/etherscan/links.js @@ -14,10 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +export const url = (isTestnet = false) => { + return `https://${isTestnet ? 'testnet.' : ''}etherscan.io`; +}; + export const txLink = (hash, isTestnet = false) => { - return `https://${isTestnet ? 'testnet.' : ''}etherscan.io/tx/${hash}`; + return `${url(isTestnet)}/tx/${hash}`; }; export const addressLink = (address, isTestnet = false) => { - return `https://${isTestnet ? 'testnet.' : ''}etherscan.io/address/${address}`; + return `${url(isTestnet)}/address/${address}`; }; diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js index 1185199e1..bfe7cabc4 100644 --- a/js/src/api/contract/contract.js +++ b/js/src/api/contract/contract.js @@ -240,8 +240,8 @@ export default class Contract { } _bindEvent = (event) => { - event.subscribe = (options = {}, callback) => { - return this._subscribe(event, options, callback); + event.subscribe = (options = {}, callback, autoRemove) => { + return this._subscribe(event, options, callback, autoRemove); }; event.unsubscribe = (subscriptionId) => { @@ -306,16 +306,31 @@ export default class Contract { return this._api.eth.newFilter(options); } - subscribe (eventName = null, options = {}, callback) { + subscribe (eventName = null, options = {}, callback, autoRemove) { try { const event = this._findEvent(eventName); - return this._subscribe(event, options, callback); + return this._subscribe(event, options, callback, autoRemove); } catch (e) { return Promise.reject(e); } } - _subscribe (event = null, _options, callback) { + _sendData (subscriptionId, error, logs) { + const { autoRemove, callback } = this._subscriptions[subscriptionId]; + let result = true; + + try { + result = callback(error, logs); + } catch (error) { + console.warn('_sendData', subscriptionId, error); + } + + if (autoRemove && result && typeof result === 'boolean') { + this.unsubscribe(subscriptionId); + } + } + + _subscribe (event = null, _options, callback, autoRemove = false) { const subscriptionId = nextSubscriptionId++; const { skipInitFetch } = _options; delete _options['skipInitFetch']; @@ -325,6 +340,7 @@ export default class Contract { .then((filterId) => { this._subscriptions[subscriptionId] = { options: _options, + autoRemove, callback, filterId }; @@ -337,8 +353,7 @@ export default class Contract { return this._api.eth .getFilterLogs(filterId) .then((logs) => { - callback(null, this.parseEventLogs(logs)); - + this._sendData(subscriptionId, null, this.parseEventLogs(logs)); this._subscribeToChanges(); return subscriptionId; }); @@ -437,13 +452,13 @@ export default class Contract { }) ) .then((logsArray) => { - logsArray.forEach((logs, idx) => { + logsArray.forEach((logs, subscriptionId) => { if (!logs || !logs.length) { return; } try { - subscriptions[idx].callback(null, this.parseEventLogs(logs)); + this.sendData(subscriptionId, null, this.parseEventLogs(logs)); } catch (error) { console.error('_sendSubscriptionChanges', error); } diff --git a/js/src/api/subscriptions/manager.js b/js/src/api/subscriptions/manager.js index bc9632592..25e6e6129 100644 --- a/js/src/api/subscriptions/manager.js +++ b/js/src/api/subscriptions/manager.js @@ -59,7 +59,7 @@ export default class Manager { return subscription; } - subscribe (subscriptionName, callback) { + subscribe (subscriptionName, callback, autoRemove = false) { return new Promise((resolve, reject) => { const subscription = this._validateType(subscriptionName); @@ -75,6 +75,7 @@ export default class Manager { this.subscriptions[subscriptionId] = { name: subscriptionName, id: subscriptionId, + autoRemove, callback }; @@ -101,13 +102,18 @@ export default class Manager { } _sendData (subscriptionId, error, data) { - const { callback } = this.subscriptions[subscriptionId]; + const { autoRemove, callback } = this.subscriptions[subscriptionId]; + let result = true; try { - callback(error, data); + result = callback(error, data); } catch (error) { console.error(`Unable to update callback for subscriptionId ${subscriptionId}`, error); } + + if (autoRemove && result && typeof result === 'boolean') { + this.unsubscribe(subscriptionId); + } } _updateSubscriptions = (subscriptionName, error, data) => { diff --git a/js/src/contracts/code/index.js b/js/src/contracts/code/index.js index baa144979..ff6d218eb 100644 --- a/js/src/contracts/code/index.js +++ b/js/src/contracts/code/index.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import wallet from './wallet'; +import { wallet } from './wallet'; export { wallet diff --git a/js/src/contracts/code/wallet.js b/js/src/contracts/code/wallet.js index 94aa04b7b..92bcf8795 100644 --- a/js/src/contracts/code/wallet.js +++ b/js/src/contracts/code/wallet.js @@ -16,8 +16,14 @@ /** * @version Solidity v0.4.6 - * @from https://github.com/ethereum/dapp-bin/blob/dd5c485359074d49f571693ae064ce78970f3d6d/wallet/wallet.sol - * @date 22-Nov-2016 @ 15h00 UTC + * @from https://github.com/ethcore/parity/blob/63137b15482344ff9df634c086abaabed452eadc/js/src/contracts/snippets/enhanced-wallet.sol + * @date 09-Dec-2016 @ 16h00 UTC */ -export default '0x606060405234610000576040516113bb3803806113bb83398101604090815281516020830151918301519201915b805b83835b815160019081019055600033600160a060020a03166003825b505550600160a060020a033316600090815261010260205260408120600190555b82518110156100ee57828181518110156100005790602001906020020151600160a060020a0316600282600201610100811015610000570160005b5081905550806002016101026000858481518110156100005790602001906020020151600160a060020a03168152602001908152602001600020819055505b60010161006c565b60008290555b50505061010581905561011264010000000061127861012182021704565b610107555b505b50505061012b565b6201518042045b90565b611282806101396000396000f3606060405236156100da5760e060020a6000350463173825d981146101305780632f54bf6e146101425780634123cb6b1461016657806352375093146101855780635c52c2f5146101a4578063659010e7146101b35780637065cb48146101d2578063746c9171146101e4578063797af62714610203578063b20d30a914610227578063b61d27f614610239578063b75c7dc61461026b578063ba51a6df1461027d578063c2cf73261461028f578063c41a360a146102b6578063cbf0b0c0146102e2578063f00d4b5d146102f4578063f1736d8614610309575b61012e5b600034111561012b5760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b5b565b005b346100005761012e600435610328565b005b3461000057610152600435610415565b604080519115158252519081900360200190f35b3461000057610173610436565b60408051918252519081900360200190f35b346100005761017361043c565b60408051918252519081900360200190f35b346100005761012e610443565b005b346100005761017361047b565b60408051918252519081900360200190f35b346100005761012e600435610482565b005b3461000057610173610571565b60408051918252519081900360200190f35b3461000057610152600435610577565b604080519115158252519081900360200190f35b346100005761012e6004356107e3565b005b34610000576101736004803590602480359160443591820191013561081c565b60408051918252519081900360200190f35b346100005761012e600435610ab3565b005b346100005761012e600435610b5e565b005b3461000057610152600435602435610be0565b604080519115158252519081900360200190f35b34610000576102c6600435610c35565b60408051600160a060020a039092168252519081900360200190f35b346100005761012e600435610c55565b005b346100005761012e600435602435610c93565b005b3461000057610173610d8c565b60408051918252519081900360200190f35b600060003660405180838380828437820191505092505050604051809103902061035181610d93565b1561040e57600160a060020a03831660009081526101026020526040902054915081151561037e5761040e565b60016001540360005411156103925761040e565b6000600283610100811015610000570160005b5055600160a060020a038316600090815261010260205260408120556103c9610f32565b6103d1611002565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b5b5b505050565b600160a060020a03811660009081526101026020526040812054115b919050565b60015481565b6101075481565b60003660405180838380828437820191505092505050604051809103902061046a81610d93565b15610476576000610106555b5b5b50565b6101065481565b6000366040518083838082843782019150509250505060405180910390206104a981610d93565b1561056b576104b782610415565b156104c15761056b565b6104c9610f32565b60015460fa90106104dc576104dc611002565b5b60015460fa90106104ed5761056b565b60018054810190819055600160a060020a03831690600290610100811015610000570160005b5055600154600160a060020a03831660008181526101026020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5b5b5050565b60005481565b60008161058381610d93565b156107da5760008381526101086020526040902054600160a060020a0316156107da5760008381526101086020526040908190208054600180830154935160029384018054600160a060020a0390941695949093919283928592918116156101000260001901160480156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b505091505060006040518083038185876185025a03f15050506000848152610108602090815260409182902060018082015482548551600160a060020a033381811683529682018c905296810183905295166060860181905260a06080870181815260029586018054958616156101000260001901909516959095049087018190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975094958a95929491939290919060c08301908490801561073d5780601f106107125761010080835404028352916020019161073d565b820191906000526020600020905b81548152906001019060200180831161072057829003601f168201915b5050965050505050505060405180910390a16000838152610108602052604081208054600160a060020a0319168155600180820183905560028083018054858255939493909281161561010002600019011604601f81901061079f57506107d1565b601f0160209004906000526020600020908101906107d191905b808211156107cd57600081556001016107b9565b5090565b5b505050600191505b5b5b5b50919050565b60003660405180838380828437820191505092505050604051809103902061080a81610d93565b1561056b576101058290555b5b5b5050565b600061082733610415565b15610aa85761083584611131565b156108f3577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a0316815260200180602001828103825284848281815260200192508082843760405192018290039850909650505050505050a184600160a060020a03168484846040518083838082843782019150509250505060006040518083038185876185025a03f15060009350610aa892505050565b6000364360405180848480828437820191505082815260200193505050506040518091039020905061092481610577565b158015610947575060008181526101086020526040902054600160a060020a0316155b15610aa857600081815261010860209081526040822080546c01000000000000000000000000808a0204600160a060020a0319909116178155600180820188905560029182018054818652948490209094601f928116156101000260001901169290920481019290920481019185919087908390106109d15782800160ff198235161785556109fe565b828001600101855582156109fe579182015b828111156109fe5782358255916020019190600101906109e3565b5b50610a1f9291505b808211156107cd57600081556001016107b9565b5090565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32813386888787604051808760001916815260200186600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284376040519201829003995090975050505050505050a15b5b5b5b949350505050565b600160a060020a033316600090815261010260205260408120549080821515610adb57610b57565b50506000828152610103602052604081206001810154600284900a929083161115610b575780546001908101825581018054839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610b8581610d93565b1561056b57600154821115610b995761056b565b6000829055610ba6610f32565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15b5b5b5050565b600082815261010360209081526040808320600160a060020a038516845261010290925282205482811515610c185760009350610c2c565b8160020a9050808360010154166000141593505b50505092915050565b6000600282600101610100811015610000570160005b505490505b919050565b600036604051808383808284378201915050925050506040518091039020610c7c81610d93565b1561056b5781600160a060020a0316ff5b5b5b5050565b6000600036604051808383808284378201915050925050506040518091039020610cbc81610d93565b15610b5757610cca83610415565b15610cd457610b57565b600160a060020a038416600090815261010260205260409020549150811515610cfc57610b57565b610d04610f32565b82600160a060020a0316600283610100811015610000570160005b5055600160a060020a0380851660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b5b5b50505050565b6101055481565b600160a060020a033316600090815261010260205260408120548180821515610dbb57610f28565b60008581526101036020526040902080549092501515610e4f576000805483556001808401919091556101048054918201808255828015829011610e2457600083815260209020610e249181019083015b808211156107cd57600081556001016107b9565b5090565b5b50505060028301819055610104805487929081101561000057906000526020600020900160005b50555b8260020a90508082600101541660001415610f285760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610f155760008581526101036020526040902060020154610104805490919081101561000057906000526020600020900160005b506000908190558581526101036020526040812081815560018082018390556002909101919091559350610f2856610f28565b8154600019018255600182018054821790555b5b5b505050919050565b6101045460005b81811015610ff557610108600061010483815481101561000057906000526020600020900160005b50548152602081019190915260400160009081208054600160a060020a0319168155600180820183905560028083018054858255939493909281161561010002600019011604601f819010610fb65750610fe8565b601f016020900490600052602060002090810190610fe891905b808211156107cd57600081556001016107b9565b5090565b5b5050505b600101610f39565b61056b6111a4565b5b5050565b60015b600154811015610476575b600154811080156110325750600281610100811015610000570160005b505415155b1561103f57600101611010565b5b600160015411801561106457506002600154610100811015610000570160005b5054155b156110785760018054600019019055611040565b6001548110801561109c57506002600154610100811015610000570160005b505415155b80156110b85750600281610100811015610000570160005b5054155b15611128576002600154610100811015610000570160005b5054600282610100811015610000570160005b5055806101026000600283610100811015610000570160005b505481526020019081526020016000208190555060006002600154610100811015610000570160005b50555b611005565b5b50565b600061113c33610415565b15610431576101075461114d611278565b111561116657600061010655611161611278565b610107555b610106548281011080159061118357506101055482610106540111155b1561119957506101068054820190556001610431565b5060005b5b5b919050565b6101045460005b818110156112215761010481815481101561000057906000526020600020900160005b50541561121857610103600061010483815481101561000057906000526020600020900160005b505481526020810191909152604001600090812081815560018101829055600201555b5b6001016111ab565b610104805460008083559190915261040e907f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156107cd57600081556001016107b9565b5090565b5b505b5050565b6201518042045b9056'; +export const wallet = '0x6060604052346100005760405161041b38038061041b83398101604090815281516020830151918301519201915b604080517f696e697457616c6c657428616464726573735b5d2c75696e743235362c75696e81527f7432353629000000000000000000000000000000000000000000000000000000602080830191909152915190819003602501902084516000829052909173__WalletLibrary_________________________91600281019160049182010290819038829003903960006000600483016000866127105a03f45b505050505050505b610337806100e46000396000f36060604052361561006c5760e060020a60003504632f54bf6e81146101245780634123cb6b146101485780635237509314610167578063659010e714610186578063746c9171146101a5578063c2cf7326146101c4578063c41a360a146101eb578063f1736d8614610217575b6101225b60003411156100c15760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a161011e565b600036111561011e5773__WalletLibrary_________________________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f4156100005750505b5b5b565b005b3461000057610134600435610236565b604080519115158252519081900360200190f35b3461000057610155610297565b60408051918252519081900360200190f35b346100005761015561029d565b60408051918252519081900360200190f35b34610000576101556102a3565b60408051918252519081900360200190f35b34610000576101556102a9565b60408051918252519081900360200190f35b34610000576101346004356024356102af565b604080519115158252519081900360200190f35b34610000576101fb600435610311565b60408051600160a060020a039092168252519081900360200190f35b3461000057610155610331565b60408051918252519081900360200190f35b600073__WalletLibrary_________________________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f4156100005750506040515190505b919050565b60015481565b60045481565b60035481565b60005481565b600073__WalletLibrary_________________________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f4156100005750506040515190505b92915050565b6000600582600101610100811015610000570160005b505490505b919050565b6002548156'; +export const walletLibrary = '0x606060405234610000575b611381806100186000396000f3606060405236156100da5760e060020a6000350463173825d981146100df5780632f54bf6e146100f157806352375093146101155780635c52c2f514610134578063659010e7146101435780637065cb4814610162578063797af627146101745780639da5e0eb14610198578063b20d30a9146101aa578063b61d27f6146101bc578063b75c7dc614610227578063ba51a6df14610239578063c2cf73261461024b578063c57c5f6014610272578063cbf0b0c0146102c6578063e46dcfeb146102d8578063f00d4b5d14610331578063f1736d8614610346575b610000565b34610000576100ef600435610365565b005b3461000057610101600435610452565b604080519115158252519081900360200190f35b3461000057610122610473565b60408051918252519081900360200190f35b34610000576100ef610479565b005b34610000576101226104b0565b60408051918252519081900360200190f35b34610000576100ef6004356104b6565b005b34610000576101016004356105a5565b604080519115158252519081900360200190f35b34610000576100ef60043561081e565b005b34610000576100ef600435610832565b005b3461000057604080516020600460443581810135601f810184900484028501840190955284845261010194823594602480359560649492939190920191819084018382808284375094965061086a95505050505050565b604080519115158252519081900360200190f35b34610000576100ef600435610bcc565b005b34610000576100ef600435610c77565b005b3461000057610101600435602435610cf9565b604080519115158252519081900360200190f35b34610000576100ef6004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437509496505093359350610d4e92505050565b005b34610000576100ef600435610e13565b005b34610000576100ef60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284375094965050843594602001359350610e5192505050565b005b34610000576100ef600435602435610e6a565b005b3461000057610122610f63565b60408051918252519081900360200190f35b600060003660405180838380828437820191505092505050604051809103902061038e81610f69565b1561044b57600160a060020a0383166000908152610105602052604090205491508115156103bb5761044b565b60016001540360005411156103cf5761044b565b6000600583610100811015610000570160005b5055600160a060020a03831660009081526101056020526040812055610406611108565b61040e6111dc565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b5b5b505050565b600160a060020a03811660009081526101056020526040812054115b919050565b60045481565b6000366040518083838082843782019150509250505060405180910390206104a081610f69565b156104ab5760006003555b5b5b50565b60035481565b6000366040518083838082843782019150509250505060405180910390206104dd81610f69565b1561059f576104eb82610452565b156104f55761059f565b6104fd611108565b60015460fa9010610510576105106111dc565b5b60015460fa90106105215761059f565b60018054810190819055600160a060020a03831690600590610100811015610000570160005b5055600154600160a060020a03831660008181526101056020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5b5b5050565b6000816105b181610f69565b156108155760008381526101086020526040902054600160a060020a0316156108155760008381526101086020526040908190208054600180830154935160029384018054600160a060020a0390941695949093919283928592918116156101000260001901160480156106665780601f1061063b57610100808354040283529160200191610666565b820191906000526020600020905b81548152906001019060200180831161064957829003601f168201915b505091505060006040518083038185876185025a03f15050506000848152610108602090815260409182902060018082015482548551600160a060020a033381811683529682018c905296810183905295166060860181905260a06080870181815260029586018054958616156101000260001901909516959095049087018190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975094958a95929491939290919060c08301908490801561076b5780601f106107405761010080835404028352916020019161076b565b820191906000526020600020905b81548152906001019060200180831161074e57829003601f168201915b5050965050505050505060405180910390a1600083815261010860205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600180820183905560028083018054858255939493909281161561010002600019011604601f8190106107da575061080c565b601f01602090049060005260206000209081019061080c91905b8082111561080857600081556001016107f4565b5090565b5b505050600191505b5b5b5b50919050565b600281905561082b61130b565b6004555b50565b60003660405180838380828437820191505092505050604051809103902061085981610f69565b1561059f5760028290555b5b5b5050565b6000600061087733610452565b15610bc05761088584611315565b156109bc577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004338587866040518085600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109335780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a184600160a060020a03168484604051808280519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561099c5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f1925050509150610bc0565b600036436040518084848082843782019150508281526020019350505050604051809103902090506109ed816105a5565b158015610a10575060008181526101086020526040902054600160a060020a0316155b15610bc057600081815261010860209081526040822080546c01000000000000000000000000808a020473ffffffffffffffffffffffffffffffffffffffff199091161781556001808201889055865160029283018054818752958590209095601f9381161561010002600019011693909304820184900483019390929190880190839010610aaa57805160ff1916838001178555610ad7565b82800160010185558215610ad7579182015b82811115610ad7578251825591602001919060010190610abc565b5b50610af89291505b8082111561080857600081556001016107f4565b5090565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887604051808660001916815260200185600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610bae5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15b5b5b5b5b509392505050565b600160a060020a033316600090815261010560205260408120549080821515610bf457610c70565b50506000828152610106602052604081206001810154600284900a929083161115610c705780546001908101825581018054839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610c9e81610f69565b1561059f57600154821115610cb25761059f565b6000829055610cbf611108565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15b5b5b5050565b600082815261010660209081526040808320600160a060020a038516845261010590925282205482811515610d315760009350610d45565b8160020a9050808360010154166000141593505b50505092915050565b815160019081019055600033600160a060020a03166006825b505550600160a060020a033316600090815261010560205260408120600190558181555b825181101561044b57828181518110156100005790602001906020020151600160a060020a0316600582600201610100811015610000570160005b5081905550806002016101056000858481518110156100005790602001906020020151600160a060020a03168152602001908152602001600020819055505b600101610d8b565b5b505050565b600036604051808383808284378201915050925050506040518091039020610e3a81610f69565b1561059f5781600160a060020a0316ff5b5b5b5050565b610e5b8383610d4e565b61044b8161081e565b5b505050565b6000600036604051808383808284378201915050925050506040518091039020610e9381610f69565b15610c7057610ea183610452565b15610eab57610c70565b600160a060020a038416600090815261010560205260409020549150811515610ed357610c70565b610edb611108565b82600160a060020a0316600583610100811015610000570160005b5055600160a060020a0380851660008181526101056020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b5b5b50505050565b60025481565b600160a060020a033316600090815261010560205260408120548180821515610f91576110fe565b60008581526101066020526040902080549092501515611025576000805483556001808401919091556101078054918201808255828015829011610ffa57600083815260209020610ffa9181019083015b8082111561080857600081556001016107f4565b5090565b5b50505060028301819055610107805487929081101561000057906000526020600020900160005b50555b8260020a905080826001015416600014156110fe5760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18154600190116110eb5760008581526101066020526040902060020154610107805490919081101561000057906000526020600020900160005b5060009081905585815261010660205260408120818155600180820183905560029091019190915593506110fe566110fe565b8154600019018255600182018054821790555b5b5b505050919050565b6101075460005b818110156111855761010781815481101561000057906000526020600020900160005b50541561117c57610106600061010783815481101561000057906000526020600020900160005b505481526020810191909152604001600090812081815560018101829055600201555b5b60010161110f565b610107805460008083559190915261044b907f47c4908e245f386bfc1825973249847f4053a761ddb4880ad63c323a7b5a2a25908101905b8082111561080857600081556001016107f4565b5090565b5b505b5050565b60015b6001548110156104ab575b6001548110801561120c5750600581610100811015610000570160005b505415155b15611219576001016111ea565b5b600160015411801561123e57506005600154610100811015610000570160005b5054155b15611252576001805460001901905561121a565b6001548110801561127657506005600154610100811015610000570160005b505415155b80156112925750600581610100811015610000570160005b5054155b15611302576005600154610100811015610000570160005b5054600582610100811015610000570160005b5055806101056000600583610100811015610000570160005b505481526020019081526020016000208190555060006005600154610100811015610000570160005b50555b6111df565b5b50565b6201518042045b90565b600061132033610452565b1561046e5760045461133061130b565b111561134757600060035561134361130b565b6004555b600354828101108015906113615750600254826003540111155b1561137657506003805482019055600161046e565b5060005b5b5b91905056'; +export const walletSourceURL = 'https://github.com/ethcore/parity/blob/63137b15482344ff9df634c086abaabed452eadc/js/src/contracts/snippets/enhanced-wallet.sol'; +export const walletLibraryRegKey = 'walletLibrary'; +// Used if no Wallet Library found in registry... +// Compiled from `wallet.sol` using Solidity v0.4.6 +export const fullWalletCode = '0x606060405234610000576040516113bb3803806113bb83398101604090815281516020830151918301519201915b805b83835b815160019081019055600033600160a060020a03166003825b505550600160a060020a033316600090815261010260205260408120600190555b82518110156100ee57828181518110156100005790602001906020020151600160a060020a0316600282600201610100811015610000570160005b5081905550806002016101026000858481518110156100005790602001906020020151600160a060020a03168152602001908152602001600020819055505b60010161006c565b60008290555b50505061010581905561011264010000000061127861012182021704565b610107555b505b50505061012b565b6201518042045b90565b611282806101396000396000f3606060405236156100da5760e060020a6000350463173825d981146101305780632f54bf6e146101425780634123cb6b1461016657806352375093146101855780635c52c2f5146101a4578063659010e7146101b35780637065cb48146101d2578063746c9171146101e4578063797af62714610203578063b20d30a914610227578063b61d27f614610239578063b75c7dc61461026b578063ba51a6df1461027d578063c2cf73261461028f578063c41a360a146102b6578063cbf0b0c0146102e2578063f00d4b5d146102f4578063f1736d8614610309575b61012e5b600034111561012b5760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b5b565b005b346100005761012e600435610328565b005b3461000057610152600435610415565b604080519115158252519081900360200190f35b3461000057610173610436565b60408051918252519081900360200190f35b346100005761017361043c565b60408051918252519081900360200190f35b346100005761012e610443565b005b346100005761017361047b565b60408051918252519081900360200190f35b346100005761012e600435610482565b005b3461000057610173610571565b60408051918252519081900360200190f35b3461000057610152600435610577565b604080519115158252519081900360200190f35b346100005761012e6004356107e3565b005b34610000576101736004803590602480359160443591820191013561081c565b60408051918252519081900360200190f35b346100005761012e600435610ab3565b005b346100005761012e600435610b5e565b005b3461000057610152600435602435610be0565b604080519115158252519081900360200190f35b34610000576102c6600435610c35565b60408051600160a060020a039092168252519081900360200190f35b346100005761012e600435610c55565b005b346100005761012e600435602435610c93565b005b3461000057610173610d8c565b60408051918252519081900360200190f35b600060003660405180838380828437820191505092505050604051809103902061035181610d93565b1561040e57600160a060020a03831660009081526101026020526040902054915081151561037e5761040e565b60016001540360005411156103925761040e565b6000600283610100811015610000570160005b5055600160a060020a038316600090815261010260205260408120556103c9610f32565b6103d1611002565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b5b5b505050565b600160a060020a03811660009081526101026020526040812054115b919050565b60015481565b6101075481565b60003660405180838380828437820191505092505050604051809103902061046a81610d93565b15610476576000610106555b5b5b50565b6101065481565b6000366040518083838082843782019150509250505060405180910390206104a981610d93565b1561056b576104b782610415565b156104c15761056b565b6104c9610f32565b60015460fa90106104dc576104dc611002565b5b60015460fa90106104ed5761056b565b60018054810190819055600160a060020a03831690600290610100811015610000570160005b5055600154600160a060020a03831660008181526101026020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5b5b5050565b60005481565b60008161058381610d93565b156107da5760008381526101086020526040902054600160a060020a0316156107da5760008381526101086020526040908190208054600180830154935160029384018054600160a060020a0390941695949093919283928592918116156101000260001901160480156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b505091505060006040518083038185876185025a03f15050506000848152610108602090815260409182902060018082015482548551600160a060020a033381811683529682018c905296810183905295166060860181905260a06080870181815260029586018054958616156101000260001901909516959095049087018190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975094958a95929491939290919060c08301908490801561073d5780601f106107125761010080835404028352916020019161073d565b820191906000526020600020905b81548152906001019060200180831161072057829003601f168201915b5050965050505050505060405180910390a16000838152610108602052604081208054600160a060020a0319168155600180820183905560028083018054858255939493909281161561010002600019011604601f81901061079f57506107d1565b601f0160209004906000526020600020908101906107d191905b808211156107cd57600081556001016107b9565b5090565b5b505050600191505b5b5b5b50919050565b60003660405180838380828437820191505092505050604051809103902061080a81610d93565b1561056b576101058290555b5b5b5050565b600061082733610415565b15610aa85761083584611131565b156108f3577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a0316815260200180602001828103825284848281815260200192508082843760405192018290039850909650505050505050a184600160a060020a03168484846040518083838082843782019150509250505060006040518083038185876185025a03f15060009350610aa892505050565b6000364360405180848480828437820191505082815260200193505050506040518091039020905061092481610577565b158015610947575060008181526101086020526040902054600160a060020a0316155b15610aa857600081815261010860209081526040822080546c01000000000000000000000000808a0204600160a060020a0319909116178155600180820188905560029182018054818652948490209094601f928116156101000260001901169290920481019290920481019185919087908390106109d15782800160ff198235161785556109fe565b828001600101855582156109fe579182015b828111156109fe5782358255916020019190600101906109e3565b5b50610a1f9291505b808211156107cd57600081556001016107b9565b5090565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32813386888787604051808760001916815260200186600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284376040519201829003995090975050505050505050a15b5b5b5b949350505050565b600160a060020a033316600090815261010260205260408120549080821515610adb57610b57565b50506000828152610103602052604081206001810154600284900a929083161115610b575780546001908101825581018054839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610b8581610d93565b1561056b57600154821115610b995761056b565b6000829055610ba6610f32565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15b5b5b5050565b600082815261010360209081526040808320600160a060020a038516845261010290925282205482811515610c185760009350610c2c565b8160020a9050808360010154166000141593505b50505092915050565b6000600282600101610100811015610000570160005b505490505b919050565b600036604051808383808284378201915050925050506040518091039020610c7c81610d93565b1561056b5781600160a060020a0316ff5b5b5b5050565b6000600036604051808383808284378201915050925050506040518091039020610cbc81610d93565b15610b5757610cca83610415565b15610cd457610b57565b600160a060020a038416600090815261010260205260409020549150811515610cfc57610b57565b610d04610f32565b82600160a060020a0316600283610100811015610000570160005b5055600160a060020a0380851660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b5b5b50505050565b6101055481565b600160a060020a033316600090815261010260205260408120548180821515610dbb57610f28565b60008581526101036020526040902080549092501515610e4f576000805483556001808401919091556101048054918201808255828015829011610e2457600083815260209020610e249181019083015b808211156107cd57600081556001016107b9565b5090565b5b50505060028301819055610104805487929081101561000057906000526020600020900160005b50555b8260020a90508082600101541660001415610f285760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610f155760008581526101036020526040902060020154610104805490919081101561000057906000526020600020900160005b506000908190558581526101036020526040812081815560018082018390556002909101919091559350610f2856610f28565b8154600019018255600182018054821790555b5b5b505050919050565b6101045460005b81811015610ff557610108600061010483815481101561000057906000526020600020900160005b50548152602081019190915260400160009081208054600160a060020a0319168155600180820183905560028083018054858255939493909281161561010002600019011604601f819010610fb65750610fe8565b601f016020900490600052602060002090810190610fe891905b808211156107cd57600081556001016107b9565b5090565b5b5050505b600101610f39565b61056b6111a4565b5b5050565b60015b600154811015610476575b600154811080156110325750600281610100811015610000570160005b505415155b1561103f57600101611010565b5b600160015411801561106457506002600154610100811015610000570160005b5054155b156110785760018054600019019055611040565b6001548110801561109c57506002600154610100811015610000570160005b505415155b80156110b85750600281610100811015610000570160005b5054155b15611128576002600154610100811015610000570160005b5054600282610100811015610000570160005b5055806101026000600283610100811015610000570160005b505481526020019081526020016000208190555060006002600154610100811015610000570160005b50555b611005565b5b50565b600061113c33610415565b15610431576101075461114d611278565b111561116657600061010655611161611278565b610107555b610106548281011080159061118357506101055482610106540111155b1561119957506101068054820190556001610431565b5060005b5b5b919050565b6101045460005b818110156112215761010481815481101561000057906000526020600020900160005b50541561121857610103600061010483815481101561000057906000526020600020900160005b505481526020810191909152604001600090812081815560018101829055600201555b5b6001016111ab565b610104805460008083559190915261040e907f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156107cd57600081556001016107b9565b5090565b5b505b5050565b6201518042045b9056'; diff --git a/js/src/contracts/snippets/enhanced-wallet.sol b/js/src/contracts/snippets/enhanced-wallet.sol new file mode 100644 index 000000000..374eb595f --- /dev/null +++ b/js/src/contracts/snippets/enhanced-wallet.sol @@ -0,0 +1,460 @@ +//sol Wallet +// Multi-sig, daily-limited account proxy/wallet. +// @authors: +// Gav Wood +// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a +// single, or, crucially, each of a number of, designated owners. +// usage: +// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by +// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the +// interior is executed. +pragma solidity ^0.4.6; + +contract multisig { + // EVENTS + + // this contract can accept a confirmation, in which case + // we record owner and operation (hash) alongside it. + event Confirmation(address owner, bytes32 operation); + event Revoke(address owner, bytes32 operation); + + // some others are in the case of an owner changing. + event OwnerChanged(address oldOwner, address newOwner); + event OwnerAdded(address newOwner); + event OwnerRemoved(address oldOwner); + + // the last one is emitted if the required signatures change + event RequirementChanged(uint newRequirement); + + // Funds has arrived into the wallet (record how much). + event Deposit(address _from, uint value); + // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). + event SingleTransact(address owner, uint value, address to, bytes data); + // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). + event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data); + // Confirmation still needed for a transaction. + event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); +} + +contract multisigAbi is multisig { + function isOwner(address _addr) returns (bool); + + function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool); + + function confirm(bytes32 _h) returns(bool); + + // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. + function setDailyLimit(uint _newLimit); + + function addOwner(address _owner); + + function removeOwner(address _owner); + + function changeRequirement(uint _newRequired); + + // Revokes a prior confirmation of the given operation + function revoke(bytes32 _operation); + + function changeOwner(address _from, address _to); + + function execute(address _to, uint _value, bytes _data) returns(bool); +} + +contract WalletLibrary is multisig { + // TYPES + + // struct for the status of a pending operation. + struct PendingState { + uint yetNeeded; + uint ownersDone; + uint index; + } + + // Transaction structure to remember details of transaction lest it need be saved for a later call. + struct Transaction { + address to; + uint value; + bytes data; + } + + /****************************** + ***** MULTI OWNED SECTION **** + ******************************/ + + // MODIFIERS + + // simple single-sig function modifier. + modifier onlyowner { + if (isOwner(msg.sender)) + _; + } + // multi-sig function modifier: the operation must have an intrinsic hash in order + // that later attempts can be realised as the same underlying operation and + // thus count as confirmations. + modifier onlymanyowners(bytes32 _operation) { + if (confirmAndCheck(_operation)) + _; + } + + // METHODS + + // constructor is given number of sigs required to do protected "onlymanyowners" transactions + // as well as the selection of addresses capable of confirming them. + function initMultiowned(address[] _owners, uint _required) { + m_numOwners = _owners.length + 1; + m_owners[1] = uint(msg.sender); + m_ownerIndex[uint(msg.sender)] = 1; + m_required = _required; + + for (uint i = 0; i < _owners.length; ++i) + { + m_owners[2 + i] = uint(_owners[i]); + m_ownerIndex[uint(_owners[i])] = 2 + i; + } + } + + // Revokes a prior confirmation of the given operation + function revoke(bytes32 _operation) { + uint ownerIndex = m_ownerIndex[uint(msg.sender)]; + // make sure they're an owner + if (ownerIndex == 0) return; + uint ownerIndexBit = 2**ownerIndex; + var pending = m_pending[_operation]; + if (pending.ownersDone & ownerIndexBit > 0) { + pending.yetNeeded++; + pending.ownersDone -= ownerIndexBit; + Revoke(msg.sender, _operation); + } + } + + // Replaces an owner `_from` with another `_to`. + function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) { + if (isOwner(_to)) return; + uint ownerIndex = m_ownerIndex[uint(_from)]; + if (ownerIndex == 0) return; + + clearPending(); + m_owners[ownerIndex] = uint(_to); + m_ownerIndex[uint(_from)] = 0; + m_ownerIndex[uint(_to)] = ownerIndex; + OwnerChanged(_from, _to); + } + + function addOwner(address _owner) onlymanyowners(sha3(msg.data)) { + if (isOwner(_owner)) return; + + clearPending(); + if (m_numOwners >= c_maxOwners) + reorganizeOwners(); + if (m_numOwners >= c_maxOwners) + return; + m_numOwners++; + m_owners[m_numOwners] = uint(_owner); + m_ownerIndex[uint(_owner)] = m_numOwners; + OwnerAdded(_owner); + } + + function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) { + uint ownerIndex = m_ownerIndex[uint(_owner)]; + if (ownerIndex == 0) return; + if (m_required > m_numOwners - 1) return; + + m_owners[ownerIndex] = 0; + m_ownerIndex[uint(_owner)] = 0; + clearPending(); + reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot + OwnerRemoved(_owner); + } + + function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) { + if (_newRequired > m_numOwners) return; + m_required = _newRequired; + clearPending(); + RequirementChanged(_newRequired); + } + + function isOwner(address _addr) returns (bool) { + return m_ownerIndex[uint(_addr)] > 0; + } + + + function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { + var pending = m_pending[_operation]; + uint ownerIndex = m_ownerIndex[uint(_owner)]; + + // make sure they're an owner + if (ownerIndex == 0) return false; + + // determine the bit to set for this owner. + uint ownerIndexBit = 2**ownerIndex; + return !(pending.ownersDone & ownerIndexBit == 0); + } + + // INTERNAL METHODS + + function confirmAndCheck(bytes32 _operation) internal returns (bool) { + // determine what index the present sender is: + uint ownerIndex = m_ownerIndex[uint(msg.sender)]; + // make sure they're an owner + if (ownerIndex == 0) return; + + var pending = m_pending[_operation]; + // if we're not yet working on this operation, switch over and reset the confirmation status. + if (pending.yetNeeded == 0) { + // reset count of confirmations needed. + pending.yetNeeded = m_required; + // reset which owners have confirmed (none) - set our bitmap to 0. + pending.ownersDone = 0; + pending.index = m_pendingIndex.length++; + m_pendingIndex[pending.index] = _operation; + } + // determine the bit to set for this owner. + uint ownerIndexBit = 2**ownerIndex; + // make sure we (the message sender) haven't confirmed this operation previously. + if (pending.ownersDone & ownerIndexBit == 0) { + Confirmation(msg.sender, _operation); + // ok - check if count is enough to go ahead. + if (pending.yetNeeded <= 1) { + // enough confirmations: reset and run interior. + delete m_pendingIndex[m_pending[_operation].index]; + delete m_pending[_operation]; + return true; + } + else + { + // not enough: record that this owner in particular confirmed. + pending.yetNeeded--; + pending.ownersDone |= ownerIndexBit; + } + } + } + + function reorganizeOwners() private { + uint free = 1; + while (free < m_numOwners) + { + while (free < m_numOwners && m_owners[free] != 0) free++; + while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; + if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) + { + m_owners[free] = m_owners[m_numOwners]; + m_ownerIndex[m_owners[free]] = free; + m_owners[m_numOwners] = 0; + } + } + } + + function clearPending() internal { + uint length = m_pendingIndex.length; + for (uint i = 0; i < length; ++i) + if (m_pendingIndex[i] != 0) + delete m_pending[m_pendingIndex[i]]; + delete m_pendingIndex; + } + + + /****************************** + ****** DAY LIMIT SECTION ***** + ******************************/ + + // MODIFIERS + + // simple modifier for daily limit. + modifier limitedDaily(uint _value) { + if (underLimit(_value)) + _; + } + + // METHODS + + // constructor - stores initial daily limit and records the present day's index. + function initDaylimit(uint _limit) { + m_dailyLimit = _limit; + m_lastDay = today(); + } + // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. + function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) { + m_dailyLimit = _newLimit; + } + // resets the amount already spent today. needs many of the owners to confirm. + function resetSpentToday() onlymanyowners(sha3(msg.data)) { + m_spentToday = 0; + } + + // INTERNAL METHODS + + // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and + // returns true. otherwise just returns false. + function underLimit(uint _value) internal onlyowner returns (bool) { + // reset the spend limit if we're on a different day to last time. + if (today() > m_lastDay) { + m_spentToday = 0; + m_lastDay = today(); + } + // check to see if there's enough left - if so, subtract and return true. + // overflow protection // dailyLimit check + if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { + m_spentToday += _value; + return true; + } + return false; + } + + // determines today's index. + function today() private constant returns (uint) { return now / 1 days; } + + + /****************************** + ********* WALLET SECTION ***** + ******************************/ + + // METHODS + + // constructor - just pass on the owner array to the multiowned and + // the limit to daylimit + function initWallet(address[] _owners, uint _required, uint _daylimit) { + initMultiowned(_owners, _required); + initDaylimit(_daylimit) ; + } + + // kills the contract sending everything to `_to`. + function kill(address _to) onlymanyowners(sha3(msg.data)) { + suicide(_to); + } + + // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. + // If not, goes into multisig process. We provide a hash on return to allow the sender to provide + // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value + // and _data arguments). They still get the option of using them if they want, anyways. + function execute(address _to, uint _value, bytes _data) onlyowner returns(bool _callValue) { + // first, take the opportunity to check that we're under the daily limit. + if (underLimit(_value)) { + SingleTransact(msg.sender, _value, _to, _data); + // yes - just execute the call. + _callValue =_to.call.value(_value)(_data); + } else { + // determine our operation hash. + bytes32 _r = sha3(msg.data, block.number); + if (!confirm(_r) && m_txs[_r].to == 0) { + m_txs[_r].to = _to; + m_txs[_r].value = _value; + m_txs[_r].data = _data; + ConfirmationNeeded(_r, msg.sender, _value, _to, _data); + } + } + } + + // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order + // to determine the body of the transaction from the hash provided. + function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { + if (m_txs[_h].to != 0) { + m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data); + MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data); + delete m_txs[_h]; + return true; + } + } + + // INTERNAL METHODS + + function clearWalletPending() internal { + uint length = m_pendingIndex.length; + for (uint i = 0; i < length; ++i) + delete m_txs[m_pendingIndex[i]]; + clearPending(); + } + + // FIELDS + address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; + + // the number of owners that must confirm the same operation before it is run. + uint m_required; + // pointer used to find a free slot in m_owners + uint m_numOwners; + + uint public m_dailyLimit; + uint public m_spentToday; + uint public m_lastDay; + + // list of owners + uint[256] m_owners; + uint constant c_maxOwners = 250; + + // index on the list of owners to allow reverse lookup + mapping(uint => uint) m_ownerIndex; + // the ongoing operations. + mapping(bytes32 => PendingState) m_pending; + bytes32[] m_pendingIndex; + + // pending transactions we have at present. + mapping (bytes32 => Transaction) m_txs; +} + + +contract Wallet is multisig { + + // WALLET CONSTRUCTOR + // calls the `initWallet` method of the Library in this context + function Wallet(address[] _owners, uint _required, uint _daylimit) { + // Signature of the Wallet Library's init function + bytes4 sig = bytes4(sha3("initWallet(address[],uint256,uint256)")); + address target = _walletLibrary; + + // Compute the size of the call data : arrays has 2 + // 32bytes for offset and length, plus 32bytes per element ; + // plus 2 32bytes for each uint + uint argarraysize = (2 + _owners.length); + uint argsize = (2 + argarraysize) * 32; + + assembly { + // Add the signature first to memory + mstore(0x0, sig) + // Add the call data, which is at the end of the + // code + codecopy(0x4, sub(codesize, argsize), argsize) + // Delegate call to the library + delegatecall(sub(gas, 10000), target, 0x0, add(argsize, 0x4), 0x0, 0x0) + } + } + + // METHODS + + // gets called when no other function matches + function() payable { + // just being sent some cash? + if (msg.value > 0) + Deposit(msg.sender, msg.value); + else if (msg.data.length > 0) + _walletLibrary.delegatecall(msg.data); + } + + // Gets an owner by 0-indexed position (using numOwners as the count) + function getOwner(uint ownerIndex) constant returns (address) { + return address(m_owners[ownerIndex + 1]); + } + + // As return statement unavailable in fallback, explicit the method here + + function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { + return _walletLibrary.delegatecall(msg.data); + } + + function isOwner(address _addr) returns (bool) { + return _walletLibrary.delegatecall(msg.data); + } + + // FIELDS + address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; + + // the number of owners that must confirm the same operation before it is run. + uint public m_required; + // pointer used to find a free slot in m_owners + uint public m_numOwners; + + uint public m_dailyLimit; + uint public m_spentToday; + uint public m_lastDay; + + // list of owners + uint[256] m_owners; +} diff --git a/js/src/jsonrpc/rollup.config.js b/js/src/jsonrpc/rollup.config.js deleted file mode 100644 index cc4f8c931..000000000 --- a/js/src/jsonrpc/rollup.config.js +++ /dev/null @@ -1,12 +0,0 @@ -import babel from 'rollup-plugin-babel'; - -export default { - entry: 'src/index.js', - dest: 'release/index.js', - format: 'cjs', - plugins: [babel({ - babelrc: false, - presets: ['es2015-rollup', 'stage-0'], - runtimeHelpers: true - })] -}; diff --git a/js/src/modals/AddAddress/addAddress.js b/js/src/modals/AddAddress/addAddress.js index 590287e73..e44cb0b3c 100644 --- a/js/src/modals/AddAddress/addAddress.js +++ b/js/src/modals/AddAddress/addAddress.js @@ -19,7 +19,7 @@ import ContentAdd from 'material-ui/svg-icons/content/add'; import ContentClear from 'material-ui/svg-icons/content/clear'; import { Button, Modal, Form, Input, InputAddress } from '~/ui'; -import { ERRORS, validateAddress, validateName } from '../../util/validation'; +import { ERRORS, validateAddress, validateName } from '~/util/validation'; export default class AddAddress extends Component { static contextTypes = { diff --git a/js/src/modals/AddContract/addContract.js b/js/src/modals/AddContract/addContract.js index 71f8a911d..b19398001 100644 --- a/js/src/modals/AddContract/addContract.js +++ b/js/src/modals/AddContract/addContract.js @@ -21,7 +21,7 @@ import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forwa import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back'; import { Button, Modal, Form, Input, InputAddress, RadioButtons } from '~/ui'; -import { ERRORS, validateAbi, validateAddress, validateName } from '../../util/validation'; +import { ERRORS, validateAbi, validateAddress, validateName } from '~/util/validation'; import { eip20, wallet } from '~/contracts/abi'; diff --git a/js/src/modals/CreateWallet/WalletType/walletType.js b/js/src/modals/CreateWallet/WalletType/walletType.js index 868c6ad9b..93dd818f1 100644 --- a/js/src/modals/CreateWallet/WalletType/walletType.js +++ b/js/src/modals/CreateWallet/WalletType/walletType.js @@ -17,6 +17,7 @@ import React, { Component, PropTypes } from 'react'; import { RadioButtons } from '~/ui'; +import { walletSourceURL } from '~/contracts/code/wallet'; // import styles from '../createWallet.css'; @@ -46,7 +47,9 @@ export default class WalletType extends Component { description: ( Create/Deploy a - standard multi-signature + + standard multi-signature + Wallet ) diff --git a/js/src/modals/CreateWallet/createWalletStore.js b/js/src/modals/CreateWallet/createWalletStore.js index d8c308a12..3edf8f638 100644 --- a/js/src/modals/CreateWallet/createWalletStore.js +++ b/js/src/modals/CreateWallet/createWalletStore.js @@ -16,13 +16,13 @@ import { observable, computed, action, transaction } from 'mobx'; -import { validateUint, validateAddress, validateName } from '~/util/validation'; -import { ERROR_CODES } from '~/api/transport/error'; - import Contract from '~/api/contract'; +import Contracts from '~/contracts'; +import { ERROR_CODES } from '~/api/transport/error'; import { wallet as walletAbi } from '~/contracts/abi'; -import { wallet as walletCode } from '~/contracts/code'; +import { wallet as walletCode, walletLibraryRegKey, fullWalletCode } from '~/contracts/code/wallet'; +import { validateUint, validateAddress, validateName } from '~/util/validation'; import WalletsUtils from '~/util/wallets'; const STEPS = { @@ -160,14 +160,25 @@ export default class CreateWalletStore { const { account, owners, required, daylimit } = this.wallet; - const options = { - data: walletCode, - from: account - }; + Contracts + .get() + .registry + .lookupAddress(walletLibraryRegKey) + .then((address) => { + const walletLibraryAddress = (address || '').replace(/^0x/, '').toLowerCase(); + const code = walletLibraryAddress.length && !/^0+$/.test(walletLibraryAddress) + ? walletCode.replace(/(_)+WalletLibrary(_)+/g, walletLibraryAddress) + : fullWalletCode; - this.api - .newContract(walletAbi) - .deploy(options, [ owners, required, daylimit ], this.onDeploymentState) + const options = { + data: code, + from: account + }; + + return this.api + .newContract(walletAbi) + .deploy(options, [ owners, required, daylimit ], this.onDeploymentState); + }) .then((address) => { this.deployed = true; this.wallet.address = address; diff --git a/js/src/modals/DeployContract/DetailsStep/detailsStep.js b/js/src/modals/DeployContract/DetailsStep/detailsStep.js index 54ef8f850..aa0a30e55 100644 --- a/js/src/modals/DeployContract/DetailsStep/detailsStep.js +++ b/js/src/modals/DeployContract/DetailsStep/detailsStep.js @@ -18,8 +18,8 @@ import React, { Component, PropTypes } from 'react'; import { MenuItem } from 'material-ui'; import { AddressSelect, Form, Input, Select } from '~/ui'; -import { validateAbi } from '../../../util/validation'; -import { parseAbiType } from '../../../util/abi'; +import { validateAbi } from '~/util/validation'; +import { parseAbiType } from '~/util/abi'; export default class DetailsStep extends Component { static contextTypes = { diff --git a/js/src/modals/DeployContract/ParametersStep/parametersStep.js b/js/src/modals/DeployContract/ParametersStep/parametersStep.js index 4c7228b67..4ab5df693 100644 --- a/js/src/modals/DeployContract/ParametersStep/parametersStep.js +++ b/js/src/modals/DeployContract/ParametersStep/parametersStep.js @@ -32,7 +32,7 @@ import React, { Component, PropTypes } from 'react'; import { Form, TypedInput } from '~/ui'; -import { parseAbiType } from '../../../util/abi'; +import { parseAbiType } from '~/util/abi'; import styles from '../deployContract.css'; diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index ae5578e40..5bf4fc389 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -19,7 +19,7 @@ import ActionDoneAll from 'material-ui/svg-icons/action/done-all'; import ContentClear from 'material-ui/svg-icons/content/clear'; import { BusyStep, CompletedStep, CopyToClipboard, Button, IdentityIcon, Modal, TxHash } from '~/ui'; -import { ERRORS, validateAbi, validateCode, validateName } from '../../util/validation'; +import { ERRORS, validateAbi, validateCode, validateName } from '~/util/validation'; import DetailsStep from './DetailsStep'; import ParametersStep from './ParametersStep'; diff --git a/js/src/modals/EditMeta/editMeta.js b/js/src/modals/EditMeta/editMeta.js index ad26c19fe..8ab9233f1 100644 --- a/js/src/modals/EditMeta/editMeta.js +++ b/js/src/modals/EditMeta/editMeta.js @@ -19,7 +19,7 @@ import ContentClear from 'material-ui/svg-icons/content/clear'; import ContentSave from 'material-ui/svg-icons/content/save'; import { Button, Form, Input, InputChip, Modal } from '~/ui'; -import { validateName } from '../../util/validation'; +import { validateName } from '~/util/validation'; export default class EditMeta extends Component { static contextTypes = { diff --git a/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js b/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js index b4488729a..3ffb929a9 100644 --- a/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js +++ b/js/src/modals/ExecuteContract/DetailsStep/detailsStep.js @@ -15,13 +15,19 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; -import { MenuItem } from 'material-ui'; +import { Checkbox, MenuItem } from 'material-ui'; import { AddressSelect, Form, Input, Select, TypedInput } from '~/ui'; import { parseAbiType } from '~/util/abi'; import styles from '../executeContract.css'; +const CHECK_STYLE = { + position: 'absolute', + top: '38px', + left: '1em' +}; + export default class DetailsStep extends Component { static propTypes = { accounts: PropTypes.object.isRequired, @@ -31,10 +37,12 @@ export default class DetailsStep extends Component { onAmountChange: PropTypes.func.isRequired, fromAddress: PropTypes.string, fromAddressError: PropTypes.string, + gasEdit: PropTypes.bool, onFromAddressChange: PropTypes.func.isRequired, func: PropTypes.object, funcError: PropTypes.string, onFuncChange: PropTypes.func, + onGasEditClick: PropTypes.func, values: PropTypes.array.isRequired, valuesError: PropTypes.array.isRequired, warning: PropTypes.string, @@ -42,7 +50,7 @@ export default class DetailsStep extends Component { } render () { - const { accounts, amount, amountError, fromAddress, fromAddressError, onFromAddressChange, onAmountChange } = this.props; + const { accounts, amount, amountError, fromAddress, fromAddressError, gasEdit, onGasEditClick, onFromAddressChange, onAmountChange } = this.props; return (
@@ -56,12 +64,23 @@ export default class DetailsStep extends Component { onChange={ onFromAddressChange } /> { this.renderFunctionSelect() } { this.renderParameters() } - +
+
+ +
+
+ +
+
); } diff --git a/js/src/modals/ExecuteContract/executeContract.css b/js/src/modals/ExecuteContract/executeContract.css index a83b373ee..6b7132912 100644 --- a/js/src/modals/ExecuteContract/executeContract.css +++ b/js/src/modals/ExecuteContract/executeContract.css @@ -42,3 +42,15 @@ padding: 0.75em; text-align: center; } + +.columns { + display: flex; + flex-wrap: wrap; + position: relative; + + &>div { + flex: 0 1 50%; + width: 50%; + position: relative; + } +} diff --git a/js/src/modals/ExecuteContract/executeContract.js b/js/src/modals/ExecuteContract/executeContract.js index 4a708d17a..7b4e8ccd2 100644 --- a/js/src/modals/ExecuteContract/executeContract.js +++ b/js/src/modals/ExecuteContract/executeContract.js @@ -17,19 +17,36 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { observer } from 'mobx-react'; import ActionDoneAll from 'material-ui/svg-icons/action/done-all'; import ContentClear from 'material-ui/svg-icons/content/clear'; +import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back'; +import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward'; -import { BusyStep, CompletedStep, Button, IdentityIcon, Modal, TxHash } from '~/ui'; -import { MAX_GAS_ESTIMATION } from '../../util/constants'; -import { validateAddress, validateUint } from '../../util/validation'; +import { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash } from '~/ui'; +import { MAX_GAS_ESTIMATION } from '~/util/constants'; +import { validateAddress, validateUint } from '~/util/validation'; import { parseAbiType } from '~/util/abi'; import DetailsStep from './DetailsStep'; -import ERRORS from '../Transfer/errors'; import { ERROR_CODES } from '~/api/transport/error'; +const STEP_DETAILS = 0; +const STEP_BUSY_OR_GAS = 1; +const STEP_BUSY = 2; + +const TITLES = { + transfer: 'function details', + sending: 'sending', + complete: 'complete', + gas: 'gas selection', + rejected: 'rejected' +}; +const STAGES_BASIC = [TITLES.transfer, TITLES.sending, TITLES.complete]; +const STAGES_GAS = [TITLES.transfer, TITLES.gas, TITLES.sending, TITLES.complete]; + +@observer class ExecuteContract extends Component { static contextTypes = { api: PropTypes.object.isRequired, @@ -46,21 +63,22 @@ class ExecuteContract extends Component { onFromAddressChange: PropTypes.func.isRequired } + gasStore = new GasPriceEditor.Store(this.context.api, this.props.gasLimit); + state = { amount: '0', amountError: null, + busyState: null, fromAddressError: null, func: null, funcError: null, - gas: null, - gasLimitError: null, + gasEdit: false, + rejected: false, + step: STEP_DETAILS, + sending: false, values: [], valuesError: [], - step: 0, - sending: false, - busyState: null, - txhash: null, - rejected: false + txhash: null } componentDidMount () { @@ -79,15 +97,21 @@ class ExecuteContract extends Component { } render () { - const { sending } = this.state; + const { sending, step, gasEdit, rejected } = this.state; + const steps = gasEdit ? STAGES_GAS : STAGES_BASIC; + + if (rejected) { + steps[steps.length - 1] = TITLES.rejected; + } return ( + current={ step } + steps={ steps } + visible + waiting={ gasEdit ? [STEP_BUSY] : [STEP_BUSY_OR_GAS] }> { this.renderStep() } ); @@ -95,7 +119,7 @@ class ExecuteContract extends Component { renderDialogActions () { const { onClose, fromAddress } = this.props; - const { sending, step, fromAddressError, valuesError } = this.state; + const { gasEdit, sending, step, fromAddressError, valuesError } = this.state; const hasError = fromAddressError || valuesError.find((error) => error); const cancelBtn = ( @@ -105,21 +129,44 @@ class ExecuteContract extends Component { icon={ } onClick={ onClose } /> ); + const postBtn = ( +