diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js
index 28bad8a3b..d9ec9b03e 100644
--- a/js/src/api/contract/contract.js
+++ b/js/src/api/contract/contract.js
@@ -209,8 +209,10 @@ export default class Contract {
_bindFunction = (func) => {
func.call = (options, values = []) => {
+ const callData = this._encodeOptions(func, this._addOptionsTo(options), values);
+
return this._api.eth
- .call(this._encodeOptions(func, this._addOptionsTo(options), values))
+ .call(callData)
.then((encoded) => func.decodeOutput(encoded))
.then((tokens) => tokens.map((token) => token.value))
.then((returns) => returns.length === 1 ? returns[0] : returns);
diff --git a/js/src/contracts/code/index.js b/js/src/contracts/code/index.js
new file mode 100644
index 000000000..baa144979
--- /dev/null
+++ b/js/src/contracts/code/index.js
@@ -0,0 +1,21 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import wallet from './wallet';
+
+export {
+ wallet
+};
diff --git a/js/src/contracts/code/wallet.js b/js/src/contracts/code/wallet.js
new file mode 100644
index 000000000..a4db4459b
--- /dev/null
+++ b/js/src/contracts/code/wallet.js
@@ -0,0 +1,23 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+/**
+ * @version Solidity v0.4.6
+ * @from https://github.com/ethereum/dapp-bin/blob/dd5c485359074d49f571693ae064ce78970f3d6d/wallet/wallet.sol
+ * @date 22-Nov-2016 @ 15h00 UTC
+ */
+export default '0x606060405234620000005760405162001a0638038062001a06833981016040528080518201919060200180519060200190919080519060200190919050505b805b83835b600060018351016001819055503373ffffffffffffffffffffffffffffffffffffffff166002600161010081101562000000570160005b5081905550600161010260003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600090505b825181101562000158578281815181101562000000579060200190602002015173ffffffffffffffffffffffffffffffffffffffff1660028260020161010081101562000000570160005b50819055508060020161010260008584815181101562000000579060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b806001019050620000b4565b816000819055505b5050508061010581905550620001896200019c6401000000000262001832176401000000009004565b610107819055505b505b505050620001b1565b60006201518042811562000000570490505b90565b61184680620001c06000396000f3606060405236156100f4576000357c010000000000000000000000000000000000000000000000000000000090048063173825d91461015c5780632f54bf6e146101795780634123cb6b146101ac57806352375093146101cf5780635c52c2f5146101f2578063659010e7146102015780637065cb4814610224578063746c917114610241578063797af62714610264578063b20d30a914610297578063b61d27f6146102b4578063b75c7dc614610306578063ba51a6df14610323578063c2cf732614610340578063c41a360a1461037c578063cbf0b0c0146103c3578063f00d4b5d146103e0578063f1736d8614610406575b61015a5b6000341115610157577fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3334604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5b565b005b34610000576101776004808035906020019091905050610429565b005b34610000576101946004808035906020019091905050610553565b60405180821515815260200191505060405180910390f35b34610000576101b961058b565b6040518082815260200191505060405180910390f35b34610000576101dc610591565b6040518082815260200191505060405180910390f35b34610000576101ff610598565b005b346100005761020e6105d3565b6040518082815260200191505060405180910390f35b346100005761023f60048080359060200190919050506105da565b005b346100005761024e61070d565b6040518082815260200191505060405180910390f35b346100005761027f6004808035906020019091905050610713565b60405180821515815260200191505060405180910390f35b34610000576102b26004808035906020019091905050610abf565b005b34610000576102ec60048080359060200190919080359060200190919080359060200190820180359060200191909192905050610afa565b604051808260001916815260200191505060405180910390f35b34610000576103216004808035906020019091905050610e68565b005b346100005761033e6004808035906020019091905050610f5f565b005b34610000576103646004808035906020019091908035906020019091905050610fe7565b60405180821515815260200191505060405180910390f35b34610000576103976004808035906020019091905050611065565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576103de6004808035906020019091905050611085565b005b346100005761040460048080359060200190919080359060200190919050506110d0565b005b3461000057610413611254565b6040518082815260200191505060405180910390f35b60006000366040518083838082843782019150509250505060405180910390206104528161125b565b1561054d5761010260008473ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054915060008214156104925761054c565b60016001540360005411156104a65761054c565b6000600283610100811015610000570160005b5081905550600061010260008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506104f661147f565b6104fe61157a565b7f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da83604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b505050565b6000600061010260008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541190505b919050565b60015481565b6101075481565b6000366040518083838082843782019150509250505060405180910390206105bf8161125b565b156105cf576000610106819055505b5b5b50565b6101065481565b6000366040518083838082843782019150509250505060405180910390206106018161125b565b156107085761060f82610553565b1561061957610707565b61062161147f565b60fa6001541015156106365761063561157a565b5b60fa60015410151561064757610707565b6001600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff166002600154610100811015610000570160005b508190555060015461010260008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c382604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b5050565b60005481565b60008161071f8161125b565b15610ab857600061010860008560001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610ab65761010860008460001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661010860008560001916815260200190815260200160002060010154610108600086600019168152602001908152602001600020600201604051808280546001816001161561010002031660029004801561086d5780601f106108425761010080835404028352916020019161086d565b820191906000526020600020905b81548152906001019060200180831161085057829003601f168201915b505091505060006040518083038185876185025a03f192505050507fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a33846101086000876000191681526020019081526020016000206001015461010860008860001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610108600089600019168152602001908152602001600020600201604051808673ffffffffffffffffffffffffffffffffffffffff168152602001856000191681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252838181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156109ef5780601f106109c4576101008083540402835291602001916109ef565b820191906000526020600020905b8154815290600101906020018083116109d257829003601f168201915b5050965050505050505060405180910390a161010860008460001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201805460018160011615610100020316600290046000825580601f10610a735750610aaa565b601f016020900490600052602060002090810190610aa991905b80821115610aa5576000816000905550600101610a8d565b5090565b5b50505060019150610ab7565b5b5b5b50919050565b600036604051808383808284378201915050925050506040518091039020610ae68161125b565b15610af55781610105819055505b5b5b5050565b6000610b0533610553565b15610e5f57610b13846116c9565b15610bfc577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd0043385878686604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a18473ffffffffffffffffffffffffffffffffffffffff168484846040518083838082843782019150509250505060006040518083038185876185025a03f1925050505060006001029050610e5e565b60003643604051808484808284378201915050828152602001935050505060405180910390209050610c2d81610713565b158015610c8b5750600061010860008360001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15610e5d578461010860008360001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c01000000000000000000000000908102040217905550836101086000836000191681526020019081526020016000206001018190555082826101086000846000191681526020019081526020016000206002019190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610d6657803560ff1916838001178555610d94565b82800160010185558215610d94579182015b82811115610d93578235825591602001919060010190610d78565b5b509050610db991905b80821115610db5576000816000905550600101610d9d565b5090565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf3281338688878760405180876000191681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b5b5b5b949350505050565b60006000600061010260003373ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205492506000831415610ea957610f59565b8260020a915061010360008560001916815260200190815260200160002090506000828260010154161115610f585780600001600081548092919060010191905055508181600101600082825403925050819055507fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b3385604051808373ffffffffffffffffffffffffffffffffffffffff168152602001826000191681526020019250505060405180910390a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610f868161125b565b15610fe257600154821115610f9a57610fe1565b81600081905550610fa961147f565b7facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da826040518082815260200191505060405180910390a15b5b5b5050565b6000600060006000610103600087600019168152602001908152602001600020925061010260008673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205491506000821415611048576000935061105c565b8160020a9050600081846001015416141593505b50505092915050565b6000600260018301610100811015610000570160005b505490505b919050565b6000366040518083838082843782019150509250505060405180910390206110ac8161125b565b156110cb578173ffffffffffffffffffffffffffffffffffffffff16ff5b5b5b5050565b60006000366040518083838082843782019150509250505060405180910390206110f98161125b565b1561124d5761110783610553565b156111115761124c565b61010260008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561114c5761124c565b61115461147f565b8273ffffffffffffffffffffffffffffffffffffffff16600283610100811015610000570160005b5081905550600061010260008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508161010260008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8484604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5b5b50505050565b6101055481565b600060006000600061010260003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549250600083141561129e57611477565b61010360008660001916815260200190815260200160002091506000826000015414156113555760005482600001819055506000826001018190555061010480548091906001018154818355818115116113245781836000526020600020918201910161132391905b8082111561131f576000816000905550600101611307565b5090565b5b5050508260020181905550846101048360020154815481101561000057906000526020600020900160005b50819055505b8260020a90506000818360010154161415611476577fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda3386604051808373ffffffffffffffffffffffffffffffffffffffff168152602001826000191681526020019250505060405180910390a16001826000015411151561144d5761010461010360008760001916815260200190815260200160002060020154815481101561000057906000526020600020900160005b5060009055610103600086600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550506001935061147756611475565b8160000160008154809291906001900391905055508082600101600082825417925050819055505b5b5b505050919050565b60006000610104805490509150600090505b8181101561156d57610108600061010483815481101561000057906000526020600020900160005b505460001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201805460018160011615610100020316600290046000825580601f10611527575061155e565b601f01602090049060005260206000209081019061155d91905b80821115611559576000816000905550600101611541565b5090565b5b5050505b806001019050611491565b61157561174f565b5b5050565b6000600190505b6001548110156116c5575b600154811080156115b057506000600282610100811015610000570160005b505414155b156115c257808060010191505061158c565b5b60016001541180156115e9575060006002600154610100811015610000570160005b5054145b1561160657600160008154809291906001900391905055506115c3565b6001548110801561162c575060006002600154610100811015610000570160005b505414155b801561164a57506000600282610100811015610000570160005b5054145b156116c0576002600154610100811015610000570160005b5054600282610100811015610000570160005b5081905550806101026000600284610100811015610000570160005b505481526020019081526020016000208190555060006002600154610100811015610000570160005b50819055505b611581565b5b50565b60006116d433610553565b1561174957610107546116e5611832565b1115611704576000610106819055506116fc611832565b610107819055505b610106548261010654011015801561172457506101055482610106540111155b1561174357816101066000828254019250508190555060019050611748565b600090505b5b5b919050565b60006000610104805490509150600090505b818110156117f357600060010261010482815481101561000057906000526020600020900160005b5054600019161415156117e757610103600061010483815481101561000057906000526020600020900160005b5054600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550505b5b806001019050611761565b6101048054600082559060005260206000209081019061182b91905b8082111561182757600081600090555060010161180f565b5090565b5b505b5050565b600062015180428115610000570490505b9056';
+
diff --git a/js/src/contracts/snippets/wallet.sol b/js/src/contracts/snippets/wallet.sol
new file mode 100644
index 000000000..b369eea76
--- /dev/null
+++ b/js/src/contracts/snippets/wallet.sol
@@ -0,0 +1,388 @@
+//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 multiowned {
+
+ // TYPES
+
+ // struct for the status of a pending operation.
+ struct PendingState {
+ uint yetNeeded;
+ uint ownersDone;
+ uint index;
+ }
+
+ // EVENTS
+
+ // this contract only has six types of events: it 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);
+
+ // 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 multiowned(address[] _owners, uint _required) {
+ m_numOwners = _owners.length + 1;
+ m_owners[1] = uint(msg.sender);
+ m_ownerIndex[uint(msg.sender)] = 1;
+ for (uint i = 0; i < _owners.length; ++i)
+ {
+ m_owners[2 + i] = uint(_owners[i]);
+ m_ownerIndex[uint(_owners[i])] = 2 + i;
+ }
+ m_required = _required;
+ }
+
+ // Revokes a prior confirmation of the given operation
+ function revoke(bytes32 _operation) external {
+ 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)) external {
+ 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)) external {
+ 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)) external {
+ 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)) external {
+ if (_newRequired > m_numOwners) return;
+ m_required = _newRequired;
+ clearPending();
+ RequirementChanged(_newRequired);
+ }
+
+ // Gets an owner by 0-indexed position (using numOwners as the count)
+ function getOwner(uint ownerIndex) external constant returns (address) {
+ return address(m_owners[ownerIndex + 1]);
+ }
+
+ 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;
+ }
+
+ // FIELDS
+
+ // 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;
+
+ // 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;
+}
+
+// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
+// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
+// uses is specified in the modifier.
+contract daylimit is multiowned {
+
+ // 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 daylimit(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)) external {
+ m_dailyLimit = _newLimit;
+ }
+ // resets the amount already spent today. needs many of the owners to confirm.
+ function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
+ 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; }
+
+ // FIELDS
+
+ uint public m_dailyLimit;
+ uint public m_spentToday;
+ uint public m_lastDay;
+}
+
+// interface contract for multisig proxy contracts; see below for docs.
+contract multisig {
+
+ // EVENTS
+
+ // logged events:
+ // 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);
+
+ // FUNCTIONS
+
+ // TODO: document
+ function changeOwner(address _from, address _to) external;
+ function execute(address _to, uint _value, bytes _data) external returns (bytes32);
+ function confirm(bytes32 _h) returns (bool);
+}
+
+// usage:
+// bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data);
+// Wallet(w).from(anotherOwner).confirm(h);
+contract Wallet is multisig, multiowned, daylimit {
+
+ // TYPES
+
+ // Transaction structure to remember details of transaction lest it need be saved for a later call.
+ struct Transaction {
+ address to;
+ uint value;
+ bytes data;
+ }
+
+ // METHODS
+
+ // constructor - just pass on the owner array to the multiowned and
+ // the limit to daylimit
+ function Wallet(address[] _owners, uint _required, uint _daylimit)
+ multiowned(_owners, _required) daylimit(_daylimit) {
+ }
+
+ // kills the contract sending everything to `_to`.
+ function kill(address _to) onlymanyowners(sha3(msg.data)) external {
+ suicide(_to);
+ }
+
+ // gets called when no other function matches
+ function() payable {
+ // just being sent some cash?
+ if (msg.value > 0)
+ Deposit(msg.sender, msg.value);
+ }
+
+ // 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) external onlyowner returns (bytes32 _r) {
+ // 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.
+ _to.call.value(_value)(_data);
+ return 0;
+ }
+ // determine our operation hash.
+ _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 clearPending() internal {
+ uint length = m_pendingIndex.length;
+ for (uint i = 0; i < length; ++i)
+ delete m_txs[m_pendingIndex[i]];
+ super.clearPending();
+ }
+
+ // FIELDS
+
+ // pending transactions we have at present.
+ mapping (bytes32 => Transaction) m_txs;
+}
diff --git a/js/src/main.js b/js/src/main.js
index ae785cbb6..d508c50fc 100644
--- a/js/src/main.js
+++ b/js/src/main.js
@@ -17,7 +17,7 @@
import React, { Component, PropTypes } from 'react';
import { Redirect, Router, Route } from 'react-router';
-import { Accounts, Account, Addresses, Address, Application, Contract, Contracts, WriteContract, Dapp, Dapps, Settings, SettingsBackground, SettingsParity, SettingsProxy, SettingsViews, Signer, Status } from '~/views';
+import { Accounts, Account, Addresses, Address, Application, Contract, Contracts, WriteContract, Wallet, Dapp, Dapps, Settings, SettingsBackground, SettingsParity, SettingsProxy, SettingsViews, Signer, Status } from '~/views';
import styles from './reset.css';
@@ -37,6 +37,7 @@ export default class MainApplication extends Component {
+
diff --git a/js/src/modals/CreateAccount/NewAccount/newAccount.js b/js/src/modals/CreateAccount/NewAccount/newAccount.js
index a100ab19a..bbbf6fed3 100644
--- a/js/src/modals/CreateAccount/NewAccount/newAccount.js
+++ b/js/src/modals/CreateAccount/NewAccount/newAccount.js
@@ -192,8 +192,6 @@ export default class CreateAccount extends Component {
};
});
- console.log(accounts);
-
this.setState({
selectedAddress: addresses[0],
accounts: accounts
@@ -201,8 +199,7 @@ export default class CreateAccount extends Component {
});
})
.catch((error) => {
- console.log('createIdentities', error);
-
+ console.error('createIdentities', error);
setTimeout(this.createIdentities, 1000);
this.newError(error);
});
diff --git a/js/src/modals/CreateWallet/WalletDetails/index.js b/js/src/modals/CreateWallet/WalletDetails/index.js
new file mode 100644
index 000000000..266385511
--- /dev/null
+++ b/js/src/modals/CreateWallet/WalletDetails/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+export default from './walletDetails';
diff --git a/js/src/modals/CreateWallet/WalletDetails/walletDetails.js b/js/src/modals/CreateWallet/WalletDetails/walletDetails.js
new file mode 100644
index 000000000..9126fdb72
--- /dev/null
+++ b/js/src/modals/CreateWallet/WalletDetails/walletDetails.js
@@ -0,0 +1,111 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import React, { Component, PropTypes } from 'react';
+
+import { Form, TypedInput, Input, AddressSelect } from '../../../ui';
+import { parseAbiType } from '../../../util/abi';
+
+export default class WalletDetails extends Component {
+ static propTypes = {
+ accounts: PropTypes.object.isRequired,
+ wallet: PropTypes.object.isRequired,
+ errors: PropTypes.object.isRequired,
+ onChange: PropTypes.func.isRequired
+ };
+
+ render () {
+ const { accounts, wallet, errors } = this.props;
+
+ return (
+
+ );
+ }
+
+ onAccoutChange = (_, account) => {
+ this.props.onChange({ account });
+ }
+
+ onNameChange = (_, name) => {
+ this.props.onChange({ name });
+ }
+
+ onDescriptionChange = (_, description) => {
+ this.props.onChange({ description });
+ }
+
+ onOwnersChange = (owners) => {
+ this.props.onChange({ owners });
+ }
+
+ onRequiredChange = (required) => {
+ this.props.onChange({ required });
+ }
+
+ onDaylimitChange = (daylimit) => {
+ this.props.onChange({ daylimit });
+ }
+}
diff --git a/js/src/modals/CreateWallet/WalletInfo/index.js b/js/src/modals/CreateWallet/WalletInfo/index.js
new file mode 100644
index 000000000..975e7bd59
--- /dev/null
+++ b/js/src/modals/CreateWallet/WalletInfo/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+export default from './walletInfo';
diff --git a/js/src/modals/CreateWallet/WalletInfo/walletInfo.js b/js/src/modals/CreateWallet/WalletInfo/walletInfo.js
new file mode 100644
index 000000000..301263314
--- /dev/null
+++ b/js/src/modals/CreateWallet/WalletInfo/walletInfo.js
@@ -0,0 +1,85 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import React, { Component, PropTypes } from 'react';
+
+import { CompletedStep, IdentityIcon, CopyToClipboard } from '../../../ui';
+
+import styles from '../createWallet.css';
+
+export default class WalletInfo extends Component {
+ static propTypes = {
+ accounts: PropTypes.object.isRequired,
+ account: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
+ address: PropTypes.string.isRequired,
+ owners: PropTypes.array.isRequired,
+ required: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number
+ ]).isRequired,
+ daylimit: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number
+ ]).isRequired
+ };
+
+ render () {
+ const { address, required, daylimit, name } = this.props;
+
+ return (
+
+
{ name } has been deployed at
+
+
+
+
{ address }
+
+
with the following owners
+
+ { this.renderOwners() }
+
+
+ { required } owners are required to confirm a transaction.
+