diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 3c87f649a..1921e80cd 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1209,8 +1209,9 @@ string Main::renderDiff(StateDiff const& _d) const if (ad.balance) { - s << "<br/>" << indent << "Balance " << dec << formatBalance(ad.balance.to()); - s << " <b>" << showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << noshowpos << "</b>"; + s << "<br/>" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]"; + auto d = (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())); + s << " <b>" << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << "</b>"; } if (ad.nonce) { @@ -1219,7 +1220,7 @@ string Main::renderDiff(StateDiff const& _d) const } if (ad.code) { - s << "<br/>" << indent << "Code " << hex << ad.code.to().size() << " bytes"; + s << "<br/>" << indent << "Code " << dec << ad.code.to().size() << " bytes"; if (ad.code.from().size()) s << " (" << ad.code.from().size() << " bytes)"; } diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index ee2074cd1..980cb9081 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -45,6 +45,12 @@ bytes padded(bytes _b, unsigned _l) return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); } +bytes paddedRight(bytes _b, unsigned _l) +{ + _b.resize(_l); + return _b; +} + bytes unpadded(bytes _b) { auto p = asString(_b).find_last_not_of((char)0); @@ -52,12 +58,18 @@ bytes unpadded(bytes _b) return _b; } -std::string unpadLeft(std::string _b) +bytes unpadLeft(bytes _b) { - auto p = _b.find_first_not_of('0'); - if (p == std::string::npos) - return "0"; - return _b.substr(p, _b.length() - 1); + unsigned int i = 0; + if (_b.size() == 0) + return _b; + + while (i < _b.size() && _b[i] == byte(0)) + i++; + + if (i != 0) + _b.erase(_b.begin(), _b.begin() + i); + return _b; } std::string prettyU256(u256 _n) diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 8e6c5fe53..59e6c1d34 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -48,12 +48,14 @@ inline std::string toJS(dev::bytes const& _n) /// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex. bytes jsToBytes(std::string const& _s); -/// Add '0' on the head of _b until _l. +/// Add '0' on the head of @a _b until @a _l. bytes padded(bytes _b, unsigned _l); +/// Add '0' on the queue of @a _b until @a _l. +bytes paddedRight(bytes _b, unsigned _l); /// Removing all trailing '0'. Returns empty array if input contains only '0' char. bytes unpadded(bytes _s); -/// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'. -std::string unpadLeft(std::string _s); +/// Remove all 0 byte on the head of @a _s. +bytes unpadLeft(bytes _s); /// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256. std::string prettyU256(u256 _n); /// Convert h256 into user-readable string (by directly using std::string constructor). diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 8de20c21d..c530beef1 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -63,22 +63,31 @@ vector<pair<u256, string>> const& units() return g_units; } -std::string formatBalance(u256 _b) +std::string formatBalance(bigint const& _b) { ostringstream ret; - if (_b > g_units[0].first * 10000) + u256 b; + if (_b < 0) { - ret << (_b / g_units[0].first) << " " << g_units[0].second; + ret << "-"; + b = (u256)-_b; + } + else + b = (u256)_b; + + if (b > g_units[0].first * 10000) + { + ret << (b / g_units[0].first) << " " << g_units[0].second; return ret.str(); } ret << setprecision(5); for (auto const& i: g_units) - if (i.first != 1 && _b >= i.first * 100) + if (i.first != 1 && b >= i.first * 100) { - ret << (double(_b / (i.first / 1000)) / 1000.0) << " " << i.second; + ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second; return ret.str(); } - ret << _b << " wei"; + ret << b << " wei"; return ret.str(); } diff --git a/libethcore/CommonEth.h b/libethcore/CommonEth.h index 704e354a2..966794953 100644 --- a/libethcore/CommonEth.h +++ b/libethcore/CommonEth.h @@ -39,7 +39,7 @@ extern const unsigned c_protocolVersion; extern const unsigned c_databaseVersion; /// User-friendly string representation of the amount _b in wei. -std::string formatBalance(u256 _b); +std::string formatBalance(bigint const& _b); /// Get information concerning the currency denominations. std::vector<std::pair<u256, std::string>> const& units(); diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp new file mode 100644 index 000000000..04713dc7e --- /dev/null +++ b/libethereum/CanonBlockChain.cpp @@ -0,0 +1,12 @@ +#include "CanonBlockChain.h" + +CanonBlockChain::CanonBlockChain() +{ + +} + +CanonBlockChain::~CanonBlockChain() +{ + +} + diff --git a/libethereum/CanonBlockChain.h b/libethereum/CanonBlockChain.h new file mode 100644 index 000000000..bc17e23ac --- /dev/null +++ b/libethereum/CanonBlockChain.h @@ -0,0 +1,12 @@ +#ifndef CANONBLOCKCHAIN_H +#define CANONBLOCKCHAIN_H + + +class CanonBlockChain +{ +public: + CanonBlockChain(); + ~CanonBlockChain(); +}; + +#endif // CANONBLOCKCHAIN_H diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index ccff335b6..9cfd18b2d 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -226,7 +226,7 @@ void Client::uninstallWatch(unsigned _i) void Client::noteChanged(h256Set const& _filters) { Guard l(m_filterLock); - cnote << "noteChanged(" << _filters << ")"; +// cnote << "noteChanged(" << _filters << ")"; // accrue all changes left in each filter into the watches. for (auto& i: m_watches) if (_filters.count(i.second.id)) @@ -361,13 +361,12 @@ void Client::setupState(State& _s) cwork << "SETUP MINE"; _s = m_postMine; } - _s.setUncles(m_bc); if (m_paranoia) { if (_s.amIJustParanoid(m_bc)) { cnote << "I'm just paranoid. Block is fine."; - _s.commitToMine(); + _s.commitToMine(m_bc); } else { @@ -375,7 +374,7 @@ void Client::setupState(State& _s) } } else - _s.commitToMine(); + _s.commitToMine(m_bc); } void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 831696beb..3f81cd4c9 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -639,8 +639,7 @@ void State::uncommitToMine() bool State::amIJustParanoid(BlockChain const& _bc) { - setUncles(_bc); - commitToMine(); + commitToMine(_bc); // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); @@ -683,8 +682,20 @@ LogBloom State::logBloom() const return ret; } -void State::setUncles(BlockChain const& _bc) +void State::commitToMine(BlockChain const& _bc) { + uncommitToMine(); + +// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); +#ifdef ETH_PARANOIA + commit(); + cnote << "Pre-reward stateRoot:" << m_state.root(); +#endif + + m_lastTx = m_db; + + Addresses uncleAddresses; + RLPStream unclesData; unsigned unclesCount = 0; if (m_previousBlock != BlockChain::genesis()) @@ -703,26 +714,11 @@ void State::setUncles(BlockChain const& _bc) BlockInfo ubi(_bc.block(u)); ubi.streamRLP(unclesData, WithNonce); ++unclesCount; + uncleAddresses.push_back(ubi.coinbaseAddress); } } } - RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); - m_currentBlock.sha3Uncles = sha3(m_currentUncles); -} - -void State::commitToMine() -{ - uncommitToMine(); - -// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); -#ifdef ETH_PARANOIA - commit(); - cnote << "Pre-reward stateRoot:" << m_state.root(); -#endif - - m_lastTx = m_db; - MemoryDB tm; GenericTrieDB<MemoryDB> transactionsTrie(&tm); transactionsTrie.init(); @@ -752,13 +748,12 @@ void State::commitToMine() txs.swapOut(m_currentTxs); + RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); + m_currentBlock.transactionsRoot = transactionsTrie.root(); m_currentBlock.receiptsRoot = receiptsTrie.root(); m_currentBlock.logBloom = logBloom(); - - Addresses uncleAddresses; - for (const auto& r: RLP(m_currentUncles)) - uncleAddresses.push_back(BlockInfo::fromHeader(r.data()).coinbaseAddress); + m_currentBlock.sha3Uncles = sha3(m_currentUncles); // Apply rewards last of all. applyRewards(uncleAddresses); @@ -805,7 +800,7 @@ void State::completeMine() ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentUncles); ret.swapOut(m_currentBytes); - m_currentBlock.hash = sha3(m_currentBytes); + m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; // Quickly reset the transactions. diff --git a/libethereum/State.h b/libethereum/State.h index 313cc5c44..0a288238d 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -105,16 +105,13 @@ public: /// @returns true if all is ok. If it's false, worry. bool amIJustParanoid(BlockChain const& _bc); - /// @brief Loads current block uncles from blockchain - void setUncles(BlockChain const& _bc); - /// Prepares the current state for mining. /// Commits all transactions into the trie, compiles uncles and transactions list, applies all /// rewards and populates the current block header with the appropriate hashes. /// The only thing left to do after this is to actually mine(). /// /// This may be called multiple times and without issue. - void commitToMine(); + void commitToMine(BlockChain const& _bc); /// Attempt to find valid nonce for block that this state represents. /// This function is thread-safe. You can safely have other interactions with this object while it is happening. @@ -125,11 +122,14 @@ public: /** Commit to DB and build the final block if the previous call to mine()'s result is completion. * Typically looks like: * @code + * while (notYetMined) + * { * // lock - * commitToMine(); + * commitToMine(_blockChain); // will call uncommitToMine if a repeat. * // unlock * MineInfo info; * for (info.complete = false; !info.complete; info = mine()) {} + * } * // lock * completeMine(); * // unlock diff --git a/libjsqrc/ethereumjs/bower.json b/libjsqrc/ethereumjs/bower.json index 420618390..168f1b39a 100644 --- a/libjsqrc/ethereumjs/bower.json +++ b/libjsqrc/ethereumjs/bower.json @@ -1,7 +1,7 @@ { "name": "ethereum.js", "namespace": "ethereum", - "version": "0.0.11", + "version": "0.0.13", "description": "Ethereum Compatible JavaScript API", "main": ["./dist/ethereum.js", "./dist/ethereum.min.js"], "dependencies": { diff --git a/libjsqrc/ethereumjs/dist/ethereum.js b/libjsqrc/ethereumjs/dist/ethereum.js index 0f30280f9..564d59b4a 100644 --- a/libjsqrc/ethereumjs/dist/ethereum.js +++ b/libjsqrc/ethereumjs/dist/ethereum.js @@ -210,7 +210,7 @@ module.exports = { }; -},{"./const":2,"./formatters":6,"./types":10,"./utils":11,"./web3":12}],2:[function(require,module,exports){ +},{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -238,9 +238,32 @@ if ("build" !== 'build') {/* var BigNumber = require('bignumber.js'); // jshint ignore:line */} +var ETH_UNITS = [ + 'wei', + 'Kwei', + 'Mwei', + 'Gwei', + 'szabo', + 'finney', + 'ether', + 'grand', + 'Mether', + 'Gether', + 'Tether', + 'Pether', + 'Eether', + 'Zether', + 'Yether', + 'Nether', + 'Dether', + 'Vether', + 'Uether' +]; + module.exports = { ETH_PADDING: 32, ETH_SIGNATURE_LENGTH: 4, + ETH_UNITS: ETH_UNITS, ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } }; @@ -368,6 +391,11 @@ var addFunctionsToContract = function (contract, desc, address) { var addEventRelatedPropertiesToContract = function (contract, desc, address) { contract.address = address; + contract._onWatchEventResult = function (data) { + var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc)); + var parser = eventImpl.outputParser(matchingEvent); + return parser(data); + }; Object.defineProperty(contract, 'topic', { get: function() { @@ -386,8 +414,12 @@ var addEventsToContract = function (contract, desc, address) { var impl = function () { var params = Array.prototype.slice.call(arguments); var signature = abi.eventSignatureFromAscii(e.name); - var event = eventImpl(address, signature, e); + var event = eventImpl.inputParser(address, signature, e); var o = event.apply(null, params); + o._onWatchEventResult = function (data) { + var parser = eventImpl.outputParser(e); + return parser(data); + }; return web3.eth.watch(o); }; @@ -455,7 +487,7 @@ var contract = function (address, desc) { module.exports = contract; -},{"./abi":1,"./event":4,"./utils":11,"./web3":12}],4:[function(require,module,exports){ +},{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -481,6 +513,16 @@ module.exports = contract; var abi = require('./abi'); var utils = require('./utils'); +/// filter inputs array && returns only indexed (or not) inputs +/// @param inputs array +/// @param bool if result should be an array of indexed params on not +/// @returns array of (not?) indexed params +var filterInputs = function (inputs, indexed) { + return inputs.filter(function (current) { + return current.indexed === indexed; + }); +}; + var inputWithName = function (inputs, name) { var index = utils.findIndex(inputs, function (input) { return input.name === name; @@ -496,7 +538,7 @@ var inputWithName = function (inputs, name) { var indexedParamsToTopics = function (event, indexed) { // sort keys? return Object.keys(indexed).map(function (key) { - var inputs = [inputWithName(event.inputs, key)]; + var inputs = [inputWithName(filterInputs(event.inputs, true), key)]; var value = indexed[key]; if (value instanceof Array) { @@ -508,7 +550,7 @@ var indexedParamsToTopics = function (event, indexed) { }); }; -var implementationOfEvent = function (address, signature, event) { +var inputParser = function (address, signature, event) { // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' return function (indexed, options) { @@ -523,10 +565,66 @@ var implementationOfEvent = function (address, signature, event) { }; }; -module.exports = implementationOfEvent; +var getArgumentsObject = function (inputs, indexed, notIndexed) { + var indexedCopy = indexed.slice(); + var notIndexedCopy = notIndexed.slice(); + return inputs.reduce(function (acc, current) { + var value; + if (current.indexed) + value = indexed.splice(0, 1)[0]; + else + value = notIndexed.splice(0, 1)[0]; + + acc[current.name] = value; + return acc; + }, {}); +}; + +var outputParser = function (event) { + + return function (output) { + var result = { + event: utils.extractDisplayName(event.name), + number: output.number, + args: {} + }; + + if (!output.topic) { + return result; + } + + var indexedOutputs = filterInputs(event.inputs, true); + var indexedData = "0x" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join(""); + var indexedRes = abi.formatOutput(indexedOutputs, indexedData); + + var notIndexedOutputs = filterInputs(event.inputs, false); + var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data); + + result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes); + + return result; + }; +}; + +var getMatchingEvent = function (events, payload) { + for (var i = 0; i < events.length; i++) { + var signature = abi.eventSignatureFromAscii(events[i].name); + if (signature === payload.topic[0]) { + return events[i]; + } + } + return undefined; +}; + + +module.exports = { + inputParser: inputParser, + outputParser: outputParser, + getMatchingEvent: getMatchingEvent +}; -},{"./abi":1,"./utils":11}],5:[function(require,module,exports){ +},{"./abi":1,"./utils":12}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -565,6 +663,8 @@ var Filter = function(options, impl) { if (options.topics) { console.warn('"topics" is deprecated, use "topic" instead'); } + + this._onWatchResult = options._onWatchEventResult; // evaluate lazy properties options = { @@ -583,7 +683,7 @@ var Filter = function(options, impl) { this.callbacks = []; this.id = impl.newFilter(options); - web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); + web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this)); }; /// alias for changed* @@ -603,7 +703,8 @@ Filter.prototype.changed = function(callback) { Filter.prototype.trigger = function(messages) { for (var i = 0; i < this.callbacks.length; i++) { for (var j = 0; j < messages.length; j++) { - this.callbacks[i].call(this, messages[j]); + var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j]; + this.callbacks[i].call(this, message); } } }; @@ -626,7 +727,7 @@ Filter.prototype.logs = function () { module.exports = Filter; -},{"./web3":12}],6:[function(require,module,exports){ +},{"./web3":13}],6:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -782,7 +883,7 @@ module.exports = { }; -},{"./const":2,"./utils":11}],7:[function(require,module,exports){ +},{"./const":2,"./utils":12}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -815,40 +916,16 @@ var HttpSyncProvider = function (host) { this.host = host || 'http://localhost:8080'; }; -/// Transforms inner message to proper jsonrpc object -/// @param inner message object -/// @returns jsonrpc object -function formatJsonRpcObject(object) { - return { - jsonrpc: '2.0', - method: object.call, - params: object.args, - id: object._id - }; -} - -/// Transforms jsonrpc object to inner message -/// @param incoming jsonrpc message -/// @returns inner message object -function formatJsonRpcMessage(message) { - var object = JSON.parse(message); - - return { - _id: object.id, - data: object.result, - error: object.error - }; -} - HttpSyncProvider.prototype.send = function (payload) { - var data = formatJsonRpcObject(payload); + //var data = formatJsonRpcObject(payload); var request = new XMLHttpRequest(); request.open('POST', this.host, false); - request.send(JSON.stringify(data)); + request.send(JSON.stringify(payload)); // check request.status - return request.responseText; + var result = request.responseText; + return JSON.parse(result); }; module.exports = HttpSyncProvider; @@ -871,6 +948,73 @@ module.exports = HttpSyncProvider; You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. */ +/** @file jsonrpc.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * @date 2015 + */ + +var messageId = 1; + +/// Should be called to valid json create payload object +/// @param method of jsonrpc call, required +/// @param params, an array of method params, optional +/// @returns valid jsonrpc payload object +var toPayload = function (method, params) { + if (!method) + console.error('jsonrpc method should be specified!'); + + return { + jsonrpc: '2.0', + method: method, + params: params || [], + id: messageId++ + }; +}; + +/// Should be called to check if jsonrpc response is valid +/// @returns true if response is valid, otherwise false +var isValidResponse = function (response) { + return !!response && + !response.error && + response.jsonrpc === '2.0' && + typeof response.id === 'number' && + (!!response.result || typeof response.result === 'boolean'); +}; + +/// Should be called to create batch payload object +/// @param messages, an array of objects with method (required) and params (optional) fields +var toBatchPayload = function (messages) { + return messages.map(function (message) { + return toPayload(message.method, message.params); + }); +}; + +module.exports = { + toPayload: toPayload, + isValidResponse: isValidResponse, + toBatchPayload: toBatchPayload +}; + + + +},{}],9:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ /** @file providermanager.js * @authors: * Jeffrey Wilcke <jeff@ethdev.com> @@ -880,7 +1024,9 @@ module.exports = HttpSyncProvider; * @date 2014 */ -var web3 = require('./web3'); // jshint ignore:line +var web3 = require('./web3'); +var jsonrpc = require('./jsonrpc'); + /** * Provider manager object prototype @@ -894,25 +1040,35 @@ var web3 = require('./web3'); // jshint ignore:line var ProviderManager = function() { this.polls = []; this.provider = undefined; - this.id = 1; var self = this; var poll = function () { if (self.provider) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - var result = self.provider.send(data.data); - - result = JSON.parse(result); + var pollsBatch = self.polls.map(function (data) { + return data.data; + }); + + var payload = jsonrpc.toBatchPayload(pollsBatch); + var results = self.provider.send(payload); + + self.polls.forEach(function (data, index) { + var result = results[index]; + if (!jsonrpc.isValidResponse(result)) { + console.log(result); + return; + } + + result = result.result; // dont call the callback if result is not an array, or empty one - if (result.error || !(result.result instanceof Array) || result.result.length === 0) { + if (!(result instanceof Array) || result.length === 0) { return; } - data.callback(result.result); + data.callback(result); + }); + } setTimeout(poll, 1000); }; @@ -920,22 +1076,19 @@ var ProviderManager = function() { }; /// sends outgoing requests +/// @params data - an object with at least 'method' property ProviderManager.prototype.send = function(data) { - - data.args = data.args || []; - data._id = this.id++; + var payload = jsonrpc.toPayload(data.method, data.params); if (this.provider === undefined) { console.error('provider is not set'); return null; } - //TODO: handle error here? - var result = this.provider.send(data); - result = JSON.parse(result); + var result = this.provider.send(payload); - if (result.error) { - console.log(result.error); + if (!jsonrpc.isValidResponse(result)) { + console.log(result); return null; } @@ -966,7 +1119,7 @@ ProviderManager.prototype.stopPolling = function (pollId) { module.exports = ProviderManager; -},{"./web3":12}],9:[function(require,module,exports){ +},{"./jsonrpc":8,"./web3":13}],10:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -994,13 +1147,14 @@ var QtSyncProvider = function () { }; QtSyncProvider.prototype.send = function (payload) { - return navigator.qt.callMethod(JSON.stringify(payload)); + var result = navigator.qt.callMethod(JSON.stringify(payload)); + return JSON.parse(result); }; module.exports = QtSyncProvider; -},{}],10:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1081,7 +1235,7 @@ module.exports = { }; -},{"./formatters":6}],11:[function(require,module,exports){ +},{"./formatters":6}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1104,6 +1258,8 @@ module.exports = { * @date 2015 */ +var c = require('./const'); + /// Finds first index of array element matching pattern /// @param array /// @param callback pattern @@ -1166,7 +1322,7 @@ var extractDisplayName = function (name) { var extractTypeName = function (name) { /// TODO: make it invulnerable var length = name.indexOf('('); - return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : ""; + return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : ""; }; /// Filters all function from input abi @@ -1185,6 +1341,32 @@ var filterEvents = function (json) { }); }; +/// used to transform value/string to eth string +/// TODO: use BigNumber.js to parse int +/// TODO: add tests for it! +var toEth = function (str) { + var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; + var unit = 0; + var units = c.ETH_UNITS; + while (val > 3000 && unit < units.length - 1) + { + val /= 1000; + unit++; + } + var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); + var replaceFunction = function($0, $1, $2) { + return $1 + ',' + $2; + }; + + while (true) { + var o = s; + s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); + if (o === s) + break; + } + return s + ' ' + units[unit]; +}; + module.exports = { findIndex: findIndex, toAscii: toAscii, @@ -1192,11 +1374,12 @@ module.exports = { extractDisplayName: extractDisplayName, extractTypeName: extractTypeName, filterFunctions: filterFunctions, - filterEvents: filterEvents + filterEvents: filterEvents, + toEth: toEth }; -},{}],12:[function(require,module,exports){ +},{"./const":2}],13:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1228,28 +1411,6 @@ if ("build" !== 'build') {/* var utils = require('./utils'); -var ETH_UNITS = [ - 'wei', - 'Kwei', - 'Mwei', - 'Gwei', - 'szabo', - 'finney', - 'ether', - 'grand', - 'Mether', - 'Gether', - 'Tether', - 'Pether', - 'Eether', - 'Zether', - 'Yether', - 'Nether', - 'Dether', - 'Vether', - 'Uether' -]; - /// @returns an array of objects describing web3 api methods var web3Methods = function () { return [ @@ -1357,8 +1518,8 @@ var setupMethods = function (obj, methods) { var args = Array.prototype.slice.call(arguments); var call = typeof method.call === 'function' ? method.call(args) : method.call; return web3.provider.send({ - call: call, - args: args + method: call, + params: args }); }; }); @@ -1371,15 +1532,15 @@ var setupProperties = function (obj, properties) { var proto = {}; proto.get = function () { return web3.provider.send({ - call: property.getter + method: property.getter }); }; if (property.setter) { proto.set = function (val) { return web3.provider.send({ - call: property.setter, - args: [val] + method: property.setter, + params: [val] }); }; } @@ -1412,29 +1573,7 @@ var web3 = { }, /// used to transform value/string to eth string - /// TODO: use BigNumber.js to parse int - toEth: function(str) { - var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; - var unit = 0; - var units = ETH_UNITS; - while (val > 3000 && unit < units.length - 1) - { - val /= 1000; - unit++; - } - var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); - var replaceFunction = function($0, $1, $2) { - return $1 + ',' + $2; - }; - - while (true) { - var o = s; - s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); - if (o === s) - break; - } - return s + ' ' + units[unit]; - }, + toEth: utils.toEth, /// eth object prototype eth: { @@ -1470,11 +1609,6 @@ var web3 = { return new web3.filter(filter, shhWatch); } }, - - /// @returns true if provider is installed - haveProvider: function() { - return !!web3.provider.provider; - } }; /// setups all api methods @@ -1497,14 +1631,13 @@ var shhWatch = { setupMethods(shhWatch, shhWatchMethods()); web3.setProvider = function(provider) { - //provider.onmessage = messageHandler; // there will be no async calls, to remove web3.provider.set(provider); }; module.exports = web3; -},{"./utils":11}],"web3":[function(require,module,exports){ +},{"./utils":12}],"web3":[function(require,module,exports){ var web3 = require('./lib/web3'); var ProviderManager = require('./lib/providermanager'); web3.provider = new ProviderManager(); @@ -1517,7 +1650,7 @@ web3.abi = require('./lib/abi'); module.exports = web3; -},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":8,"./lib/qtsync":9,"./lib/web3":12}]},{},["web3"]) +},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"]) //# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/libjsqrc/ethereumjs/dist/ethereum.js.map b/libjsqrc/ethereumjs/dist/ethereum.js.map index ae0d47200..1ef0b2f76 100644 --- a/libjsqrc/ethereumjs/dist/ethereum.js.map +++ b/libjsqrc/ethereumjs/dist/ethereum.js.map @@ -9,6 +9,7 @@ "lib/filter.js", "lib/formatters.js", "lib/httpsync.js", + "lib/jsonrpc.js", "lib/providermanager.js", "lib/qtsync.js", "lib/types.js", @@ -17,23 +18,24 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar utils = require('./utils');\nvar types = require('./types');\nvar c = require('./const');\nvar f = require('./formatters');\n\nvar displayTypeError = function (type) {\n console.error('parser does not support type: ' + type);\n};\n\n/// This method should be called if we want to check if givent type is an array type\n/// @returns true if it is, otherwise false\nvar arrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\nvar dynamicTypeBytes = function (type, value) {\n // TODO: decide what to do with array of strings\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return f.formatInputInt(value.length); \n return \"\";\n};\n\nvar inputTypes = types.inputTypes(); \n\n/// Formats input params to bytes\n/// @param abi contract method inputs\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar formatInput = function (inputs, params) {\n var bytes = \"\";\n var padding = c.ETH_PADDING * 2;\n\n /// first we iterate in search for dynamic \n inputs.forEach(function (input, index) {\n bytes += dynamicTypeBytes(input.type, params[index]);\n });\n\n inputs.forEach(function (input, i) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n displayTypeError(inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n var toAppend = \"\";\n\n if (arrayType(inputs[i].type))\n toAppend = params[i].reduce(function (acc, curr) {\n return acc + formatter(curr);\n }, \"\");\n else\n toAppend = formatter(params[i]);\n\n bytes += toAppend; \n });\n return bytes;\n};\n\nvar dynamicBytesLength = function (type) {\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return c.ETH_PADDING * 2;\n return 0;\n};\n\nvar outputTypes = types.outputTypes(); \n\n/// Formats output bytes back to param list\n/// @param contract abi method outputs\n/// @param bytes representtion of output \n/// @returns array of output params \nvar formatOutput = function (outs, output) {\n \n output = output.slice(2);\n var result = [];\n var padding = c.ETH_PADDING * 2;\n\n var dynamicPartLength = outs.reduce(function (acc, curr) {\n return acc + dynamicBytesLength(curr.type);\n }, 0);\n \n var dynamicPart = output.slice(0, dynamicPartLength);\n output = output.slice(dynamicPartLength);\n\n outs.forEach(function (out, i) {\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(outs[i].type);\n }\n\n if (!typeMatch) {\n displayTypeError(outs[i].type);\n }\n\n var formatter = outputTypes[j - 1].format;\n if (arrayType(outs[i].type)) {\n var size = f.formatOutputUInt(dynamicPart.slice(0, padding));\n dynamicPart = dynamicPart.slice(padding);\n var array = [];\n for (var k = 0; k < size; k++) {\n array.push(formatter(output.slice(0, padding))); \n output = output.slice(padding);\n }\n result.push(array);\n }\n else if (types.prefixedType('string')(outs[i].type)) {\n dynamicPart = dynamicPart.slice(padding); \n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n } else {\n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n }\n });\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\n/// TODO: refactor creating the parser, do not double logic from contract\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = utils.extractDisplayName(method.name); \n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return formatInput(method.inputs, params);\n };\n \n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name); \n var typeName = utils.extractTypeName(method.name);\n\n var impl = function (output) {\n return formatOutput(method.outputs, output);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/// @param function/event name for which we want to get signature\n/// @returns signature of function/event with given name\nvar signatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);\n};\n\nvar eventSignatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n formatInput: formatInput,\n formatOutput: formatOutput,\n signatureFromAscii: signatureFromAscii,\n eventSignatureFromAscii: eventSignatureFromAscii\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file const.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar abi = require('./abi');\nvar utils = require('./utils');\nvar eventImpl = require('./event');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransact = false;\n contract._options = options;\n return contract;\n };\n\n contract.transact = function (options) {\n contract._isTransact = true;\n contract._options = options;\n return contract;\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.signatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = signature + parsed;\n \n var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransact = null;\n\n if (isTransact) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.transact(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n \n Object.defineProperty(contract, 'topic', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return abi.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.eventSignatureFromAscii(e.name);\n var event = eventImpl(address, signature, e);\n var o = event.apply(null, params);\n return web3.eth.watch(o); \n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\n};\n\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\n\nvar contract = function (address, desc) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n desc.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, desc, address);\n addEventRelatedPropertiesToContract(result, desc, address);\n addEventsToContract(result, desc, address);\n\n return result;\n};\n\nmodule.exports = contract;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file event.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2014\n */\n\nvar abi = require('./abi');\nvar utils = require('./utils');\n\nvar inputWithName = function (inputs, name) {\n var index = utils.findIndex(inputs, function (input) {\n return input.name === name;\n });\n \n if (index === -1) {\n console.error('indexed param with name ' + name + ' not found');\n return undefined;\n }\n return inputs[index];\n};\n\nvar indexedParamsToTopics = function (event, indexed) {\n // sort keys?\n return Object.keys(indexed).map(function (key) {\n var inputs = [inputWithName(event.inputs, key)];\n\n var value = indexed[key];\n if (value instanceof Array) {\n return value.map(function (v) {\n return abi.formatInput(inputs, [v]);\n }); \n }\n return abi.formatInput(inputs, [value]);\n });\n};\n\nvar implementationOfEvent = function (address, signature, event) {\n \n // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'\n return function (indexed, options) {\n var o = options || {};\n o.address = address;\n o.topic = [];\n o.topic.push(signature);\n if (indexed) {\n o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));\n }\n return o;\n };\n};\n\nmodule.exports = implementationOfEvent;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\n\n/// should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\n/// TODO: change 'options' name cause it may be not the best matching one, since we have events\nvar Filter = function(options, impl) {\n\n if (typeof options !== \"string\") {\n\n // topics property is deprecated, warn about it!\n if (options.topics) {\n console.warn('\"topics\" is deprecated, use \"topic\" instead');\n }\n\n // evaluate lazy properties\n options = {\n to: options.to,\n topic: options.topic,\n earliest: options.earliest,\n latest: options.latest,\n max: options.max,\n skip: options.skip,\n address: options.address\n };\n\n }\n \n this.impl = impl;\n this.callbacks = [];\n\n this.id = impl.newFilter(options);\n web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this));\n};\n\n/// alias for changed*\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\nFilter.prototype.happened = function(callback) {\n this.changed(callback);\n};\n\n/// gets called when there is new eth/shh message\nFilter.prototype.changed = function(callback) {\n this.callbacks.push(callback);\n};\n\n/// trigger calling new message from people\nFilter.prototype.trigger = function(messages) {\n for (var i = 0; i < this.callbacks.length; i++) {\n for (var j = 0; j < messages.length; j++) {\n this.callbacks[i].call(this, messages[j]);\n }\n }\n};\n\n/// should be called to uninstall current filter\nFilter.prototype.uninstall = function() {\n this.impl.uninstallFilter(this.id);\n web3.provider.stopPolling(this.id);\n};\n\n/// should be called to manually trigger getting latest messages from the client\nFilter.prototype.messages = function() {\n return this.impl.getMessages(this.id);\n};\n\n/// alias for messages\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nmodule.exports = Filter;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file const.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar ETH_UNITS = [ \n 'wei', \n 'Kwei', \n 'Mwei', \n 'Gwei', \n 'szabo', \n 'finney', \n 'ether', \n 'grand', \n 'Mether', \n 'Gether', \n 'Tether', \n 'Pether', \n 'Eether', \n 'Zether', \n 'Yether', \n 'Nether', \n 'Dether', \n 'Vether', \n 'Uether' \n];\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_UNITS: ETH_UNITS,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar abi = require('./abi');\nvar utils = require('./utils');\nvar eventImpl = require('./event');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransact = false;\n contract._options = options;\n return contract;\n };\n\n contract.transact = function (options) {\n contract._isTransact = true;\n contract._options = options;\n return contract;\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.signatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = signature + parsed;\n \n var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransact = null;\n\n if (isTransact) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.transact(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n contract._onWatchEventResult = function (data) {\n var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));\n var parser = eventImpl.outputParser(matchingEvent);\n return parser(data);\n };\n \n Object.defineProperty(contract, 'topic', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return abi.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.eventSignatureFromAscii(e.name);\n var event = eventImpl.inputParser(address, signature, e);\n var o = event.apply(null, params);\n o._onWatchEventResult = function (data) {\n var parser = eventImpl.outputParser(e);\n return parser(data);\n };\n return web3.eth.watch(o); \n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\n};\n\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\n\nvar contract = function (address, desc) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n desc.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, desc, address);\n addEventRelatedPropertiesToContract(result, desc, address);\n addEventsToContract(result, desc, address);\n\n return result;\n};\n\nmodule.exports = contract;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file event.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2014\n */\n\nvar abi = require('./abi');\nvar utils = require('./utils');\n\n/// filter inputs array && returns only indexed (or not) inputs\n/// @param inputs array\n/// @param bool if result should be an array of indexed params on not\n/// @returns array of (not?) indexed params\nvar filterInputs = function (inputs, indexed) {\n return inputs.filter(function (current) {\n return current.indexed === indexed;\n });\n};\n\nvar inputWithName = function (inputs, name) {\n var index = utils.findIndex(inputs, function (input) {\n return input.name === name;\n });\n \n if (index === -1) {\n console.error('indexed param with name ' + name + ' not found');\n return undefined;\n }\n return inputs[index];\n};\n\nvar indexedParamsToTopics = function (event, indexed) {\n // sort keys?\n return Object.keys(indexed).map(function (key) {\n var inputs = [inputWithName(filterInputs(event.inputs, true), key)];\n\n var value = indexed[key];\n if (value instanceof Array) {\n return value.map(function (v) {\n return abi.formatInput(inputs, [v]);\n }); \n }\n return abi.formatInput(inputs, [value]);\n });\n};\n\nvar inputParser = function (address, signature, event) {\n \n // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'\n return function (indexed, options) {\n var o = options || {};\n o.address = address;\n o.topic = [];\n o.topic.push(signature);\n if (indexed) {\n o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));\n }\n return o;\n };\n};\n\nvar getArgumentsObject = function (inputs, indexed, notIndexed) {\n var indexedCopy = indexed.slice();\n var notIndexedCopy = notIndexed.slice();\n return inputs.reduce(function (acc, current) {\n var value;\n if (current.indexed)\n value = indexed.splice(0, 1)[0];\n else\n value = notIndexed.splice(0, 1)[0];\n\n acc[current.name] = value;\n return acc;\n }, {}); \n};\n \nvar outputParser = function (event) {\n \n return function (output) {\n var result = {\n event: utils.extractDisplayName(event.name),\n number: output.number,\n args: {}\n };\n\n if (!output.topic) {\n return result;\n }\n \n var indexedOutputs = filterInputs(event.inputs, true);\n var indexedData = \"0x\" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join(\"\");\n var indexedRes = abi.formatOutput(indexedOutputs, indexedData);\n\n var notIndexedOutputs = filterInputs(event.inputs, false);\n var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);\n\n result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);\n\n return result;\n };\n};\n\nvar getMatchingEvent = function (events, payload) {\n for (var i = 0; i < events.length; i++) {\n var signature = abi.eventSignatureFromAscii(events[i].name); \n if (signature === payload.topic[0]) {\n return events[i];\n }\n }\n return undefined;\n};\n\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n getMatchingEvent: getMatchingEvent\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\n\n/// should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\n/// TODO: change 'options' name cause it may be not the best matching one, since we have events\nvar Filter = function(options, impl) {\n\n if (typeof options !== \"string\") {\n\n // topics property is deprecated, warn about it!\n if (options.topics) {\n console.warn('\"topics\" is deprecated, use \"topic\" instead');\n }\n \n this._onWatchResult = options._onWatchEventResult;\n\n // evaluate lazy properties\n options = {\n to: options.to,\n topic: options.topic,\n earliest: options.earliest,\n latest: options.latest,\n max: options.max,\n skip: options.skip,\n address: options.address\n };\n\n }\n \n this.impl = impl;\n this.callbacks = [];\n\n this.id = impl.newFilter(options);\n web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));\n};\n\n/// alias for changed*\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\nFilter.prototype.happened = function(callback) {\n this.changed(callback);\n};\n\n/// gets called when there is new eth/shh message\nFilter.prototype.changed = function(callback) {\n this.callbacks.push(callback);\n};\n\n/// trigger calling new message from people\nFilter.prototype.trigger = function(messages) {\n for (var i = 0; i < this.callbacks.length; i++) {\n for (var j = 0; j < messages.length; j++) {\n var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];\n this.callbacks[i].call(this, message);\n }\n }\n};\n\n/// should be called to uninstall current filter\nFilter.prototype.uninstall = function() {\n this.impl.uninstallFilter(this.id);\n web3.provider.stopPolling(this.id);\n};\n\n/// should be called to manually trigger getting latest messages from the client\nFilter.prototype.messages = function() {\n return this.impl.getMessages(this.id);\n};\n\n/// alias for messages\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nmodule.exports = Filter;\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file formatters.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar utils = require('./utils');\nvar c = require('./const');\n\n/// @param string string to be padded\n/// @param number of characters that result string should have\n/// @param sign, by default 0\n/// @returns right aligned string\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/// Formats input value to byte representation of int\n/// If value is negative, return it's two's complement\n/// If the value is floating point, round it down\n/// @returns right-aligned byte representation of int\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n if (value instanceof BigNumber || typeof value === 'number') {\n if (typeof value === 'number')\n value = new BigNumber(value);\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n value = value.round();\n\n if (value.lessThan(0)) \n value = new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(value).plus(1);\n value = value.toString(16);\n }\n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else if (typeof value === 'string')\n value = formatInputInt(new BigNumber(value));\n else\n value = (+value).toString(16);\n return padLeft(value, padding);\n};\n\n/// Formats input value to byte representation of string\n/// @returns left-algined byte representation of string\nvar formatInputString = function (value) {\n return utils.fromAscii(value, c.ETH_PADDING).substr(2);\n};\n\n/// Formats input value to byte representation of bool\n/// @returns right-aligned byte representation bool\nvar formatInputBool = function (value) {\n return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n};\n\n/// Formats input value to byte representation of real\n/// Values are multiplied by 2^m and encoded as integers\n/// @returns byte representation of real\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); \n};\n\n\n/// Check if input value is negative\n/// @param value is hex format\n/// @returns true if it is negative, otherwise false\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/// Formats input right-aligned input bytes to int\n/// @returns right-aligned input bytes formatted to int\nvar formatOutputInt = function (value) {\n value = value || \"0\";\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/// Formats big right-aligned input bytes to uint\n/// @returns right-aligned input bytes formatted to uint\nvar formatOutputUInt = function (value) {\n value = value || \"0\";\n return new BigNumber(value, 16);\n};\n\n/// @returns input bytes formatted to real\nvar formatOutputReal = function (value) {\n return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/// @returns input bytes formatted to ureal\nvar formatOutputUReal = function (value) {\n return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/// @returns right-aligned input bytes formatted to hex\nvar formatOutputHash = function (value) {\n return \"0x\" + value;\n};\n\n/// @returns right-aligned input bytes formatted to bool\nvar formatOutputBool = function (value) {\n return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/// @returns left-aligned input bytes formatted to ascii string\nvar formatOutputString = function (value) {\n return utils.toAscii(value);\n};\n\n/// @returns right-aligned input bytes formatted to address\nvar formatOutputAddress = function (value) {\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputString: formatInputString,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputHash: formatOutputHash,\n formatOutputBool: formatOutputBool,\n formatOutputString: formatOutputString,\n formatOutputAddress: formatOutputAddress\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file httpsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpSyncProvider = function (host) {\n this.handlers = [];\n this.host = host || 'http://localhost:8080';\n};\n\n/// Transforms inner message to proper jsonrpc object\n/// @param inner message object\n/// @returns jsonrpc object\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\n/// Transforms jsonrpc object to inner message\n/// @param incoming jsonrpc message \n/// @returns inner message object\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\nHttpSyncProvider.prototype.send = function (payload) {\n var data = formatJsonRpcObject(payload);\n \n var request = new XMLHttpRequest();\n request.open('POST', this.host, false);\n request.send(JSON.stringify(data));\n \n // check request.status\n return request.responseText;\n};\n\nmodule.exports = HttpSyncProvider;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\n\n/**\n * Provider manager object prototype\n * It's responsible for passing messages to providers\n * If no provider is set it's responsible for queuing requests\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 12 seconds\n * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,\n * and provider manager polling mechanism is not used\n */\nvar ProviderManager = function() {\n this.polls = [];\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n var result = self.provider.send(data.data);\n \n result = JSON.parse(result);\n \n // dont call the callback if result is not an array, or empty one\n if (result.error || !(result.result instanceof Array) || result.result.length === 0) {\n return;\n }\n\n data.callback(result.result);\n });\n }\n setTimeout(poll, 1000);\n };\n poll();\n};\n\n/// sends outgoing requests\nProviderManager.prototype.send = function(data) {\n\n data.args = data.args || [];\n data._id = this.id++;\n\n if (this.provider === undefined) {\n console.error('provider is not set');\n return null; \n }\n\n //TODO: handle error here? \n var result = this.provider.send(data);\n result = JSON.parse(result);\n\n if (result.error) {\n console.log(result.error);\n return null;\n }\n\n return result.result;\n};\n\n/// setups provider, which will be used for sending messages\nProviderManager.prototype.set = function(provider) {\n this.provider = provider;\n};\n\n/// this method is only used, when we do not have native qt bindings and have to do polling on our own\n/// should be callled, on start watching for eth/shh changes\nProviderManager.prototype.startPolling = function (data, pollId, callback) {\n this.polls.push({data: data, id: pollId, callback: callback});\n};\n\n/// should be called to stop polling for certain watch changes\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nmodule.exports = ProviderManager;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file qtsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nvar QtSyncProvider = function () {\n};\n\nQtSyncProvider.prototype.send = function (payload) {\n return navigator.qt.callMethod(JSON.stringify(payload));\n};\n\nmodule.exports = QtSyncProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file httpsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpSyncProvider = function (host) {\n this.handlers = [];\n this.host = host || 'http://localhost:8080';\n};\n\nHttpSyncProvider.prototype.send = function (payload) {\n //var data = formatJsonRpcObject(payload);\n \n var request = new XMLHttpRequest();\n request.open('POST', this.host, false);\n request.send(JSON.stringify(payload));\n \n // check request.status\n var result = request.responseText;\n return JSON.parse(result);\n};\n\nmodule.exports = HttpSyncProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\nvar messageId = 1;\n\n/// Should be called to valid json create payload object\n/// @param method of jsonrpc call, required\n/// @param params, an array of method params, optional\n/// @returns valid jsonrpc payload object\nvar toPayload = function (method, params) {\n if (!method)\n console.error('jsonrpc method should be specified!');\n\n return {\n jsonrpc: '2.0',\n method: method,\n params: params || [],\n id: messageId++\n }; \n};\n\n/// Should be called to check if jsonrpc response is valid\n/// @returns true if response is valid, otherwise false \nvar isValidResponse = function (response) {\n return !!response &&\n !response.error &&\n response.jsonrpc === '2.0' &&\n typeof response.id === 'number' &&\n (!!response.result || typeof response.result === 'boolean');\n};\n\n/// Should be called to create batch payload object\n/// @param messages, an array of objects with method (required) and params (optional) fields\nvar toBatchPayload = function (messages) {\n return messages.map(function (message) {\n return toPayload(message.method, message.params);\n }); \n};\n\nmodule.exports = {\n toPayload: toPayload,\n isValidResponse: isValidResponse,\n toBatchPayload: toBatchPayload\n};\n\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar jsonrpc = require('./jsonrpc');\n\n\n/**\n * Provider manager object prototype\n * It's responsible for passing messages to providers\n * If no provider is set it's responsible for queuing requests\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 12 seconds\n * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,\n * and provider manager polling mechanism is not used\n */\nvar ProviderManager = function() {\n this.polls = [];\n this.provider = undefined;\n\n var self = this;\n var poll = function () {\n if (self.provider) {\n var pollsBatch = self.polls.map(function (data) {\n return data.data;\n });\n\n var payload = jsonrpc.toBatchPayload(pollsBatch);\n var results = self.provider.send(payload);\n\n self.polls.forEach(function (data, index) {\n var result = results[index];\n \n if (!jsonrpc.isValidResponse(result)) {\n console.log(result);\n return;\n }\n\n result = result.result;\n // dont call the callback if result is not an array, or empty one\n if (!(result instanceof Array) || result.length === 0) {\n return;\n }\n\n data.callback(result);\n\n });\n\n }\n setTimeout(poll, 1000);\n };\n poll();\n};\n\n/// sends outgoing requests\n/// @params data - an object with at least 'method' property\nProviderManager.prototype.send = function(data) {\n var payload = jsonrpc.toPayload(data.method, data.params);\n\n if (this.provider === undefined) {\n console.error('provider is not set');\n return null; \n }\n\n var result = this.provider.send(payload);\n\n if (!jsonrpc.isValidResponse(result)) {\n console.log(result);\n return null;\n }\n\n return result.result;\n};\n\n/// setups provider, which will be used for sending messages\nProviderManager.prototype.set = function(provider) {\n this.provider = provider;\n};\n\n/// this method is only used, when we do not have native qt bindings and have to do polling on our own\n/// should be callled, on start watching for eth/shh changes\nProviderManager.prototype.startPolling = function (data, pollId, callback) {\n this.polls.push({data: data, id: pollId, callback: callback});\n};\n\n/// should be called to stop polling for certain watch changes\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nmodule.exports = ProviderManager;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file qtsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nvar QtSyncProvider = function () {\n};\n\nQtSyncProvider.prototype.send = function (payload) {\n var result = navigator.qt.callMethod(JSON.stringify(payload));\n return JSON.parse(result);\n};\n\nmodule.exports = QtSyncProvider;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file types.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\nvar f = require('./formatters');\n\n/// @param expected type prefix (string)\n/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false\nvar prefixedType = function (prefix) {\n return function (type) {\n return type.indexOf(prefix) === 0;\n };\n};\n\n/// @param expected type name (string)\n/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false\nvar namedType = function (name) {\n return function (type) {\n return name === type;\n };\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar inputTypes = function () {\n \n return [\n { type: prefixedType('uint'), format: f.formatInputInt },\n { type: prefixedType('int'), format: f.formatInputInt },\n { type: prefixedType('hash'), format: f.formatInputInt },\n { type: prefixedType('string'), format: f.formatInputString }, \n { type: prefixedType('real'), format: f.formatInputReal },\n { type: prefixedType('ureal'), format: f.formatInputReal },\n { type: namedType('address'), format: f.formatInputInt },\n { type: namedType('bool'), format: f.formatInputBool }\n ];\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar outputTypes = function () {\n\n return [\n { type: prefixedType('uint'), format: f.formatOutputUInt },\n { type: prefixedType('int'), format: f.formatOutputInt },\n { type: prefixedType('hash'), format: f.formatOutputHash },\n { type: prefixedType('string'), format: f.formatOutputString },\n { type: prefixedType('real'), format: f.formatOutputReal },\n { type: prefixedType('ureal'), format: f.formatOutputUReal },\n { type: namedType('address'), format: f.formatOutputAddress },\n { type: namedType('bool'), format: f.formatOutputBool }\n ];\n};\n\nmodule.exports = {\n prefixedType: prefixedType,\n namedType: namedType,\n inputTypes: inputTypes,\n outputTypes: outputTypes\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file utils.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns ascii string representation of hex value prefixed with 0x\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \nvar toHex = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/// @returns hex representation (prefixed by 0x) of ascii string\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHex(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/// @returns display name for function/event eg. multiply(uint256) -> multiply\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : \"\";\n};\n\n/// Filters all function from input abi\n/// @returns abi array with filtered objects of type 'function'\nvar filterFunctions = function (json) {\n return json.filter(function (current) {\n return current.type === 'function'; \n }); \n};\n\n/// Filters all events form input abi\n/// @returns abi array with filtered objects of type 'event'\nvar filterEvents = function (json) {\n return json.filter(function (current) {\n return current.type === 'event';\n });\n};\n\nmodule.exports = {\n findIndex: findIndex,\n toAscii: toAscii,\n fromAscii: fromAscii,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n filterFunctions: filterFunctions,\n filterEvents: filterEvents\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js');\n*/}\n\nvar utils = require('./utils');\n\nvar ETH_UNITS = [ \n 'wei', \n 'Kwei', \n 'Mwei', \n 'Gwei', \n 'szabo', \n 'finney', \n 'ether', \n 'grand', \n 'Mether', \n 'Gether', \n 'Tether', \n 'Pether', \n 'Eether', \n 'Zether', \n 'Yether', \n 'Nether', \n 'Dether', \n 'Vether', \n 'Uether' \n];\n\n/// @returns an array of objects describing web3 api methods\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth api methods\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'flush', call: 'eth_flush' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\n/// @returns an array of objects describing web3.eth api properties\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\n/// @returns an array of objects describing web3.db api methods\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh api methods\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth.watch api methods\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessages', call: 'shh_getMessages' }\n ];\n};\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n var args = Array.prototype.slice.call(arguments);\n var call = typeof method.call === 'function' ? method.call(args) : method.call;\n return web3.provider.send({\n call: call,\n args: args\n });\n };\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return web3.provider.send({\n call: property.getter\n });\n };\n\n if (property.setter) {\n proto.set = function (val) {\n return web3.provider.send({\n call: property.setter,\n args: [val]\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n /// @returns ascii string representation of hex value prefixed with 0x\n toAscii: utils.toAscii,\n\n /// @returns hex representation (prefixed by 0x) of ascii string\n fromAscii: utils.fromAscii,\n\n /// @returns decimal representaton of hex value prefixed by 0x\n toDecimal: function (val) {\n // remove 0x and place 0, if it's required\n val = val.length > 2 ? val.substring(2) : \"0\";\n return (new BigNumber(val, 16).toString(10));\n },\n\n /// @returns hex representation (prefixed by 0x) of decimal value\n fromDecimal: function (val) {\n return \"0x\" + (new BigNumber(val).toString(16));\n },\n\n /// used to transform value/string to eth string\n /// TODO: use BigNumber.js to parse int\n toEth: function(str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = ETH_UNITS;\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n },\n\n /// eth object prototype\n eth: {\n contractFromAbi: function (abi) {\n return function(addr) {\n // Default to address of Config. TODO: rremove prior to genesis.\n addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b';\n var ret = web3.eth.contract(addr, abi);\n ret.address = addr;\n return ret;\n };\n },\n\n /// @param filter may be a string, object or event\n /// @param indexed is optional, this is an object with optional event indexed params\n /// @param options is optional, this is an object with optional event options ('max'...)\n watch: function (filter, indexed, options) {\n if (filter._isEvent) {\n return filter(indexed, options);\n }\n return new web3.filter(filter, ethWatch);\n }\n },\n\n /// db object prototype\n db: {},\n\n /// shh object prototype\n shh: {\n \n /// @param filter may be a string, object or event\n watch: function (filter, indexed) {\n return new web3.filter(filter, shhWatch);\n }\n },\n\n /// @returns true if provider is installed\n haveProvider: function() {\n return !!web3.provider.provider;\n }\n};\n\n/// setups all api methods\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\n\nsetupMethods(ethWatch, ethWatchMethods());\n\nvar shhWatch = {\n changed: 'shh_changed'\n};\n\nsetupMethods(shhWatch, shhWatchMethods());\n\nweb3.setProvider = function(provider) {\n //provider.onmessage = messageHandler; // there will be no async calls, to remove\n web3.provider.set(provider);\n};\n\nmodule.exports = web3;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file utils.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2015\n */\n\nvar c = require('./const');\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns ascii string representation of hex value prefixed with 0x\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \nvar toHex = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/// @returns hex representation (prefixed by 0x) of ascii string\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHex(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/// @returns display name for function/event eg. multiply(uint256) -> multiply\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/// Filters all function from input abi\n/// @returns abi array with filtered objects of type 'function'\nvar filterFunctions = function (json) {\n return json.filter(function (current) {\n return current.type === 'function'; \n }); \n};\n\n/// Filters all events form input abi\n/// @returns abi array with filtered objects of type 'event'\nvar filterEvents = function (json) {\n return json.filter(function (current) {\n return current.type === 'event';\n });\n};\n\n/// used to transform value/string to eth string\n/// TODO: use BigNumber.js to parse int\n/// TODO: add tests for it!\nvar toEth = function (str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = c.ETH_UNITS;\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n};\n\nmodule.exports = {\n findIndex: findIndex,\n toAscii: toAscii,\n fromAscii: fromAscii,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n filterFunctions: filterFunctions,\n filterEvents: filterEvents,\n toEth: toEth\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js');\n*/}\n\nvar utils = require('./utils');\n\n/// @returns an array of objects describing web3 api methods\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth api methods\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'flush', call: 'eth_flush' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\n/// @returns an array of objects describing web3.eth api properties\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\n/// @returns an array of objects describing web3.db api methods\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh api methods\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth.watch api methods\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessages', call: 'shh_getMessages' }\n ];\n};\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n var args = Array.prototype.slice.call(arguments);\n var call = typeof method.call === 'function' ? method.call(args) : method.call;\n return web3.provider.send({\n method: call,\n params: args\n });\n };\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return web3.provider.send({\n method: property.getter\n });\n };\n\n if (property.setter) {\n proto.set = function (val) {\n return web3.provider.send({\n method: property.setter,\n params: [val]\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n /// @returns ascii string representation of hex value prefixed with 0x\n toAscii: utils.toAscii,\n\n /// @returns hex representation (prefixed by 0x) of ascii string\n fromAscii: utils.fromAscii,\n\n /// @returns decimal representaton of hex value prefixed by 0x\n toDecimal: function (val) {\n // remove 0x and place 0, if it's required\n val = val.length > 2 ? val.substring(2) : \"0\";\n return (new BigNumber(val, 16).toString(10));\n },\n\n /// @returns hex representation (prefixed by 0x) of decimal value\n fromDecimal: function (val) {\n return \"0x\" + (new BigNumber(val).toString(16));\n },\n\n /// used to transform value/string to eth string\n toEth: utils.toEth,\n\n /// eth object prototype\n eth: {\n contractFromAbi: function (abi) {\n return function(addr) {\n // Default to address of Config. TODO: rremove prior to genesis.\n addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b';\n var ret = web3.eth.contract(addr, abi);\n ret.address = addr;\n return ret;\n };\n },\n\n /// @param filter may be a string, object or event\n /// @param indexed is optional, this is an object with optional event indexed params\n /// @param options is optional, this is an object with optional event options ('max'...)\n watch: function (filter, indexed, options) {\n if (filter._isEvent) {\n return filter(indexed, options);\n }\n return new web3.filter(filter, ethWatch);\n }\n },\n\n /// db object prototype\n db: {},\n\n /// shh object prototype\n shh: {\n \n /// @param filter may be a string, object or event\n watch: function (filter, indexed) {\n return new web3.filter(filter, shhWatch);\n }\n },\n};\n\n/// setups all api methods\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\n\nsetupMethods(ethWatch, ethWatchMethods());\n\nvar shhWatch = {\n changed: 'shh_changed'\n};\n\nsetupMethods(shhWatch, shhWatchMethods());\n\nweb3.setProvider = function(provider) {\n web3.provider.set(provider);\n};\n\nmodule.exports = web3;\n\n", "var web3 = require('./lib/web3');\nvar ProviderManager = require('./lib/providermanager');\nweb3.provider = new ProviderManager();\nweb3.filter = require('./lib/filter');\nweb3.providers.HttpSyncProvider = require('./lib/httpsync');\nweb3.providers.QtSyncProvider = require('./lib/qtsync');\nweb3.eth.contract = require('./lib/contract');\nweb3.abi = require('./lib/abi');\n\n\nmodule.exports = web3;\n" ] } \ No newline at end of file diff --git a/libjsqrc/ethereumjs/dist/ethereum.min.js b/libjsqrc/ethereumjs/dist/ethereum.min.js index a745a5ed3..a2524c0ce 100644 --- a/libjsqrc/ethereumjs/dist/ethereum.min.js +++ b/libjsqrc/ethereumjs/dist/ethereum.min.js @@ -1 +1 @@ -require=function t(e,n,r){function i(a,u){if(!n[a]){if(!e[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(o)return o(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var c=n[a]={exports:{}};e[a][0].call(c.exports,function(t){var n=e[a][1][t];return i(n?n:t)},c,c.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<r.length;a++)i(r[a]);return i}({1:[function(t,e){var n=t("./web3"),r=t("./utils"),i=t("./types"),o=t("./const"),a=t("./formatters"),u=function(t){console.error("parser does not support type: "+t)},f=function(t){return"[]"===t.slice(-2)},s=function(t,e){return f(t)||"string"===t?a.formatInputInt(e.length):""},c=i.inputTypes(),l=function(t,e){{var n="";2*o.ETH_PADDING}return t.forEach(function(t,r){n+=s(t.type,e[r])}),t.forEach(function(r,i){for(var o=!1,a=0;a<c.length&&!o;a++)o=c[a].type(t[i].type,e[i]);o||u(t[i].type);var s=c[a-1].format,l="";l=f(t[i].type)?e[i].reduce(function(t,e){return t+s(e)},""):s(e[i]),n+=l}),n},p=function(t){return f(t)||"string"===t?2*o.ETH_PADDING:0},h=i.outputTypes(),m=function(t,e){e=e.slice(2);var n=[],r=2*o.ETH_PADDING,s=t.reduce(function(t,e){return t+p(e.type)},0),c=e.slice(0,s);return e=e.slice(s),t.forEach(function(o,s){for(var l=!1,p=0;p<h.length&&!l;p++)l=h[p].type(t[s].type);l||u(t[s].type);var m=h[p-1].format;if(f(t[s].type)){var d=a.formatOutputUInt(c.slice(0,r));c=c.slice(r);for(var g=[],v=0;d>v;v++)g.push(m(e.slice(0,r))),e=e.slice(r);n.push(g)}else i.prefixedType("string")(t[s].type)?(c=c.slice(r),n.push(m(e.slice(0,r))),e=e.slice(r)):(n.push(m(e.slice(0,r))),e=e.slice(r))}),n},d=function(t){var e={};return t.forEach(function(t){var n=r.extractDisplayName(t.name),i=r.extractTypeName(t.name),o=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[n]&&(e[n]=o),e[n][i]=o}),e},g=function(t){var e={};return t.forEach(function(t){var n=r.extractDisplayName(t.name),i=r.extractTypeName(t.name),o=function(e){return m(t.outputs,e)};void 0===e[n]&&(e[n]=o),e[n][i]=o}),e},v=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*o.ETH_SIGNATURE_LENGTH)},y=function(t){return n.sha3(n.fromAscii(t))};e.exports={inputParser:d,outputParser:g,formatInput:l,formatOutput:m,signatureFromAscii:v,eventSignatureFromAscii:y}},{"./const":2,"./formatters":6,"./types":10,"./utils":11,"./web3":12}],2:[function(t,e){e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN}}},{}],3:[function(t,e){var n=t("./web3"),r=t("./abi"),i=t("./utils"),o=t("./event"),a=function(t){n._currentContractAbi=t.abi,n._currentContractAddress=t.address,n._currentContractMethodName=t.method,n._currentContractMethodParams=t.params},u=function(t){t.call=function(e){return t._isTransact=!1,t._options=e,t},t.transact=function(e){return t._isTransact=!0,t._options=e,t},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},f=function(t,e,o){var u=r.inputParser(e),f=r.outputParser(e);i.filterFunctions(e).forEach(function(s){var c=i.extractDisplayName(s.name),l=i.extractTypeName(s.name),p=function(){var i=Array.prototype.slice.call(arguments),p=r.signatureFromAscii(s.name),h=u[c][l].apply(null,i),m=t._options||{};m.to=o,m.data=p+h;var d=t._isTransact===!0||t._isTransact!==!1&&!s.constant,g=m.collapse!==!1;if(t._options={},t._isTransact=null,d)return a({abi:e,address:o,method:s.name,params:i}),void n.eth.transact(m);var v=n.eth.call(m),y=f[c][l](v);return g&&(1===y.length?y=y[0]:0===y.length&&(y=null)),y};void 0===t[c]&&(t[c]=p),t[c][l]=p})},s=function(t,e,n){t.address=n,Object.defineProperty(t,"topic",{get:function(){return i.filterEvents(e).map(function(t){return r.eventSignatureFromAscii(t.name)})}})},c=function(t,e,a){i.filterEvents(e).forEach(function(e){var u=function(){var t=Array.prototype.slice.call(arguments),i=r.eventSignatureFromAscii(e.name),u=o(a,i,e),f=u.apply(null,t);return n.eth.watch(f)};u._isEvent=!0;var f=i.extractDisplayName(e.name),s=i.extractTypeName(e.name);void 0===t[f]&&(t[f]=u),t[f][s]=u})},l=function(t,e){e.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return u(n),f(n,e,t),s(n,e,t),c(n,e,t),n};e.exports=l},{"./abi":1,"./event":4,"./utils":11,"./web3":12}],4:[function(t,e){var n=t("./abi"),r=t("./utils"),i=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},o=function(t,e){return Object.keys(e).map(function(r){var o=[i(t.inputs,r)],a=e[r];return a instanceof Array?a.map(function(t){return n.formatInput(o,[t])}):n.formatInput(o,[a])})},a=function(t,e,n){return function(r,i){var a=i||{};return a.address=t,a.topic=[],a.topic.push(e),r&&(a.topic=a.topic.concat(o(n,r))),a}};e.exports=a},{"./abi":1,"./utils":11}],5:[function(t,e){var n=t("./web3"),r=function(t,e){"string"!=typeof t&&(t.topics&&console.warn('"topics" is deprecated, use "topic" instead'),t={to:t.to,topic:t.topic,earliest:t.earliest,latest:t.latest,max:t.max,skip:t.skip,address:t.address}),this.impl=e,this.callbacks=[],this.id=e.newFilter(t),n.provider.startPolling({call:e.changed,args:[this.id]},this.id,this.trigger.bind(this))};r.prototype.arrived=function(t){this.changed(t)},r.prototype.happened=function(t){this.changed(t)},r.prototype.changed=function(t){this.callbacks.push(t)},r.prototype.trigger=function(t){for(var e=0;e<this.callbacks.length;e++)for(var n=0;n<t.length;n++)this.callbacks[e].call(this,t[n])},r.prototype.uninstall=function(){this.impl.uninstallFilter(this.id),n.provider.stopPolling(this.id)},r.prototype.messages=function(){return this.impl.getMessages(this.id)},r.prototype.logs=function(){return this.messages()},e.exports=r},{"./web3":12}],6:[function(t,e){var n=t("./utils"),r=t("./const"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},o=function(t){var e=2*r.ETH_PADDING;return t instanceof BigNumber||"number"==typeof t?("number"==typeof t&&(t=new BigNumber(t)),BigNumber.config(r.ETH_BIGNUMBER_ROUNDING_MODE),t=t.round(),t.lessThan(0)&&(t=new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(t).plus(1)),t=t.toString(16)):t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?o(new BigNumber(t)):(+t).toString(16),i(t,e)},a=function(t){return n.fromAscii(t,r.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},f=function(t){return o(new BigNumber(t).times(new BigNumber(2).pow(128)))},s=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},c=function(t){return t=t||"0",s(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},l=function(t){return t=t||"0",new BigNumber(t,16)},p=function(t){return c(t).dividedBy(new BigNumber(2).pow(128))},h=function(t){return l(t).dividedBy(new BigNumber(2).pow(128))},m=function(t){return"0x"+t},d=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return n.toAscii(t)},v=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:o,formatInputString:a,formatInputBool:u,formatInputReal:f,formatOutputInt:c,formatOutputUInt:l,formatOutputReal:p,formatOutputUReal:h,formatOutputHash:m,formatOutputBool:d,formatOutputString:g,formatOutputAddress:v}},{"./const":2,"./utils":11}],7:[function(t,e){function n(t){return{jsonrpc:"2.0",method:t.call,params:t.args,id:t._id}}var r=function(t){this.handlers=[],this.host=t||"http://localhost:8080"};r.prototype.send=function(t){var e=n(t),r=new XMLHttpRequest;return r.open("POST",this.host,!1),r.send(JSON.stringify(e)),r.responseText},e.exports=r},{}],8:[function(t,e){var n=(t("./web3"),function(){this.polls=[],this.provider=void 0,this.id=1;var t=this,e=function(){t.provider&&t.polls.forEach(function(e){e.data._id=t.id,t.id++;var n=t.provider.send(e.data);n=JSON.parse(n),!n.error&&n.result instanceof Array&&0!==n.result.length&&e.callback(n.result)}),setTimeout(e,1e3)};e()});n.prototype.send=function(t){if(t.args=t.args||[],t._id=this.id++,void 0===this.provider)return console.error("provider is not set"),null;var e=this.provider.send(t);return e=JSON.parse(e),e.error?(console.log(e.error),null):e.result},n.prototype.set=function(t){this.provider=t},n.prototype.startPolling=function(t,e,n){this.polls.push({data:t,id:e,callback:n})},n.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},e.exports=n},{"./web3":12}],9:[function(t,e){var n=function(){};n.prototype.send=function(t){return navigator.qt.callMethod(JSON.stringify(t))},e.exports=n},{}],10:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},i=function(t){return function(e){return t===e}},o=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("hash"),format:n.formatInputInt},{type:r("string"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:i("address"),format:n.formatInputInt},{type:i("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("hash"),format:n.formatOutputHash},{type:r("string"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:i("address"),format:n.formatOutputAddress},{type:i("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:i,inputTypes:o,outputTypes:a}},{"./formatters":6}],11:[function(t,e){var n=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},r=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},i=function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},o=function(t,e){e=void 0===e?0:e;for(var n=i(t);n.length<2*e;)n+="00";return"0x"+n},a=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},u=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)):""},f=function(t){return t.filter(function(t){return"function"===t.type})},s=function(t){return t.filter(function(t){return"event"===t.type})};e.exports={findIndex:n,toAscii:r,fromAscii:o,extractDisplayName:a,extractTypeName:u,filterFunctions:f,filterEvents:s}},{}],12:[function(t,e){var n=t("./utils"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"],i=function(){return[{name:"sha3",call:"web3_sha3"}]},o=function(){var t=function(t){return"string"==typeof t[0]?"eth_blockByHash":"eth_blockByNumber"},e=function(t){return"string"==typeof t[0]?"eth_transactionByHash":"eth_transactionByNumber"},n=function(t){return"string"==typeof t[0]?"eth_uncleByHash":"eth_uncleByNumber"},r=[{name:"balanceAt",call:"eth_balanceAt"},{name:"stateAt",call:"eth_stateAt"},{name:"storageAt",call:"eth_storageAt"},{name:"countAt",call:"eth_countAt"},{name:"codeAt",call:"eth_codeAt"},{name:"transact",call:"eth_transact"},{name:"call",call:"eth_call"},{name:"block",call:t},{name:"transaction",call:e},{name:"uncle",call:n},{name:"compilers",call:"eth_compilers"},{name:"flush",call:"eth_flush"},{name:"lll",call:"eth_lll"},{name:"solidity",call:"eth_solidity"},{name:"serpent",call:"eth_serpent"},{name:"logs",call:"eth_logs"}];return r},a=function(){return[{name:"coinbase",getter:"eth_coinbase",setter:"eth_setCoinbase"},{name:"listening",getter:"eth_listening",setter:"eth_setListening"},{name:"mining",getter:"eth_mining",setter:"eth_setMining"},{name:"gasPrice",getter:"eth_gasPrice"},{name:"accounts",getter:"eth_accounts"},{name:"peerCount",getter:"eth_peerCount"},{name:"defaultBlock",getter:"eth_defaultBlock",setter:"eth_setDefaultBlock"},{name:"number",getter:"eth_number"}]},u=function(){return[{name:"put",call:"db_put"},{name:"get",call:"db_get"},{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"}]},f=function(){return[{name:"post",call:"shh_post"},{name:"newIdentity",call:"shh_newIdentity"},{name:"haveIdentity",call:"shh_haveIdentity"},{name:"newGroup",call:"shh_newGroup"},{name:"addToGroup",call:"shh_addToGroup"}]},s=function(){var t=function(t){return"string"==typeof t[0]?"eth_newFilterString":"eth_newFilter"};return[{name:"newFilter",call:t},{name:"uninstallFilter",call:"eth_uninstallFilter"},{name:"getMessages",call:"eth_filterLogs"}]},c=function(){return[{name:"newFilter",call:"shh_newFilter"},{name:"uninstallFilter",call:"shh_uninstallFilter"},{name:"getMessages",call:"shh_getMessages"}]},l=function(t,e){e.forEach(function(e){t[e.name]=function(){var t=Array.prototype.slice.call(arguments),n="function"==typeof e.call?e.call(t):e.call;return h.provider.send({call:n,args:t})}})},p=function(t,e){e.forEach(function(e){var n={};n.get=function(){return h.provider.send({call:e.getter})},e.setter&&(n.set=function(t){return h.provider.send({call:e.setter,args:[t]})}),Object.defineProperty(t,e.name,n)})},h={_callbacks:{},_events:{},providers:{},toAscii:n.toAscii,fromAscii:n.fromAscii,toDecimal:function(t){return t=t.length>2?t.substring(2):"0",new BigNumber(t,16).toString(10)},fromDecimal:function(t){return"0x"+new BigNumber(t).toString(16)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,i=r;e>3e3&&n<i.length-1;)e/=1e3,n++;for(var o=e.toString().length<e.toFixed(2).length?e.toString():e.toFixed(2),a=function(t,e,n){return e+","+n};;){var u=o;if(o=o.replace(/(\d)(\d\d\d[\.\,])/,a),u===o)break}return o+" "+i[n]},eth:{contractFromAbi:function(t){return function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=h.eth.contract(e,t);return n.address=e,n}},watch:function(t,e,n){return t._isEvent?t(e,n):new h.filter(t,m)}},db:{},shh:{watch:function(t){return new h.filter(t,d)}},haveProvider:function(){return!!h.provider.provider}};l(h,i()),l(h.eth,o()),p(h.eth,a()),l(h.db,u()),l(h.shh,f());var m={changed:"eth_changed"};l(m,s());var d={changed:"shh_changed"};l(d,c()),h.setProvider=function(t){h.provider.set(t)},e.exports=h},{"./utils":11}],web3:[function(t,e){var n=t("./lib/web3"),r=t("./lib/providermanager");n.provider=new r,n.filter=t("./lib/filter"),n.providers.HttpSyncProvider=t("./lib/httpsync"),n.providers.QtSyncProvider=t("./lib/qtsync"),n.eth.contract=t("./lib/contract"),n.abi=t("./lib/abi"),e.exports=n},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":8,"./lib/qtsync":9,"./lib/web3":12}]},{},["web3"]); \ No newline at end of file +require=function t(e,n,r){function i(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(o)return o(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=n[a]={exports:{}};e[a][0].call(c.exports,function(t){var n=e[a][1][t];return i(n?n:t)},c,c.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<r.length;a++)i(r[a]);return i}({1:[function(t,e){var n=t("./web3"),r=t("./utils"),i=t("./types"),o=t("./const"),a=t("./formatters"),u=function(t){console.error("parser does not support type: "+t)},s=function(t){return"[]"===t.slice(-2)},f=function(t,e){return s(t)||"string"===t?a.formatInputInt(e.length):""},c=i.inputTypes(),l=function(t,e){{var n="";2*o.ETH_PADDING}return t.forEach(function(t,r){n+=f(t.type,e[r])}),t.forEach(function(r,i){for(var o=!1,a=0;a<c.length&&!o;a++)o=c[a].type(t[i].type,e[i]);o||u(t[i].type);var f=c[a-1].format,l="";l=s(t[i].type)?e[i].reduce(function(t,e){return t+f(e)},""):f(e[i]),n+=l}),n},p=function(t){return s(t)||"string"===t?2*o.ETH_PADDING:0},m=i.outputTypes(),h=function(t,e){e=e.slice(2);var n=[],r=2*o.ETH_PADDING,f=t.reduce(function(t,e){return t+p(e.type)},0),c=e.slice(0,f);return e=e.slice(f),t.forEach(function(o,f){for(var l=!1,p=0;p<m.length&&!l;p++)l=m[p].type(t[f].type);l||u(t[f].type);var h=m[p-1].format;if(s(t[f].type)){var d=a.formatOutputUInt(c.slice(0,r));c=c.slice(r);for(var g=[],v=0;d>v;v++)g.push(h(e.slice(0,r))),e=e.slice(r);n.push(g)}else i.prefixedType("string")(t[f].type)?(c=c.slice(r),n.push(h(e.slice(0,r))),e=e.slice(r)):(n.push(h(e.slice(0,r))),e=e.slice(r))}),n},d=function(t){var e={};return t.forEach(function(t){var n=r.extractDisplayName(t.name),i=r.extractTypeName(t.name),o=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[n]&&(e[n]=o),e[n][i]=o}),e},g=function(t){var e={};return t.forEach(function(t){var n=r.extractDisplayName(t.name),i=r.extractTypeName(t.name),o=function(e){return h(t.outputs,e)};void 0===e[n]&&(e[n]=o),e[n][i]=o}),e},v=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*o.ETH_SIGNATURE_LENGTH)},y=function(t){return n.sha3(n.fromAscii(t))};e.exports={inputParser:d,outputParser:g,formatInput:l,formatOutput:h,signatureFromAscii:v,eventSignatureFromAscii:y}},{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(t,e){var n=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:n,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN}}},{}],3:[function(t,e){var n=t("./web3"),r=t("./abi"),i=t("./utils"),o=t("./event"),a=function(t){n._currentContractAbi=t.abi,n._currentContractAddress=t.address,n._currentContractMethodName=t.method,n._currentContractMethodParams=t.params},u=function(t){t.call=function(e){return t._isTransact=!1,t._options=e,t},t.transact=function(e){return t._isTransact=!0,t._options=e,t},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},s=function(t,e,o){var u=r.inputParser(e),s=r.outputParser(e);i.filterFunctions(e).forEach(function(f){var c=i.extractDisplayName(f.name),l=i.extractTypeName(f.name),p=function(){var i=Array.prototype.slice.call(arguments),p=r.signatureFromAscii(f.name),m=u[c][l].apply(null,i),h=t._options||{};h.to=o,h.data=p+m;var d=t._isTransact===!0||t._isTransact!==!1&&!f.constant,g=h.collapse!==!1;if(t._options={},t._isTransact=null,d)return a({abi:e,address:o,method:f.name,params:i}),void n.eth.transact(h);var v=n.eth.call(h),y=s[c][l](v);return g&&(1===y.length?y=y[0]:0===y.length&&(y=null)),y};void 0===t[c]&&(t[c]=p),t[c][l]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=o.outputParser(n);return r(t)},Object.defineProperty(t,"topic",{get:function(){return i.filterEvents(e).map(function(t){return r.eventSignatureFromAscii(t.name)})}})},c=function(t,e,a){i.filterEvents(e).forEach(function(e){var u=function(){var t=Array.prototype.slice.call(arguments),i=r.eventSignatureFromAscii(e.name),u=o.inputParser(a,i,e),s=u.apply(null,t);return s._onWatchEventResult=function(t){var n=o.outputParser(e);return n(t)},n.eth.watch(s)};u._isEvent=!0;var s=i.extractDisplayName(e.name),f=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=u),t[s][f]=u})},l=function(t,e){e.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return u(n),s(n,e,t),f(n,e,t),c(n,e,t),n};e.exports=l},{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(t,e){var n=t("./abi"),r=t("./utils"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},o=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},a=function(t,e){return Object.keys(e).map(function(r){var a=[o(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(a,[t])}):n.formatInput(a,[u])})},u=function(t,e,n){return function(r,i){var o=i||{};return o.address=t,o.topic=[],o.topic.push(e),r&&(o.topic=o.topic.concat(a(n,r))),o}},s=function(t,e,n){e.slice(),n.slice();return t.reduce(function(t,r){var i;return i=r.indexed?e.splice(0,1)[0]:n.splice(0,1)[0],t[r.name]=i,t},{})},f=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,args:{}};if(!e.topic)return o;var a=i(t.inputs,!0),u="0x"+e.topic.slice(1,e.topic.length).map(function(t){return t.slice(2)}).join(""),f=n.formatOutput(a,u),c=i(t.inputs,!1),l=n.formatOutput(c,e.data);return o.args=s(t.inputs,f,l),o}},c=function(t,e){for(var r=0;r<t.length;r++){var i=n.eventSignatureFromAscii(t[r].name);if(i===e.topic[0])return t[r]}return void 0};e.exports={inputParser:u,outputParser:f,getMatchingEvent:c}},{"./abi":1,"./utils":12}],5:[function(t,e){var n=t("./web3"),r=function(t,e){"string"!=typeof t&&(t.topics&&console.warn('"topics" is deprecated, use "topic" instead'),this._onWatchResult=t._onWatchEventResult,t={to:t.to,topic:t.topic,earliest:t.earliest,latest:t.latest,max:t.max,skip:t.skip,address:t.address}),this.impl=e,this.callbacks=[],this.id=e.newFilter(t),n.provider.startPolling({method:e.changed,params:[this.id]},this.id,this.trigger.bind(this))};r.prototype.arrived=function(t){this.changed(t)},r.prototype.happened=function(t){this.changed(t)},r.prototype.changed=function(t){this.callbacks.push(t)},r.prototype.trigger=function(t){for(var e=0;e<this.callbacks.length;e++)for(var n=0;n<t.length;n++){var r=this._onWatchResult?this._onWatchResult(t[n]):t[n];this.callbacks[e].call(this,r)}},r.prototype.uninstall=function(){this.impl.uninstallFilter(this.id),n.provider.stopPolling(this.id)},r.prototype.messages=function(){return this.impl.getMessages(this.id)},r.prototype.logs=function(){return this.messages()},e.exports=r},{"./web3":13}],6:[function(t,e){var n=t("./utils"),r=t("./const"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},o=function(t){var e=2*r.ETH_PADDING;return t instanceof BigNumber||"number"==typeof t?("number"==typeof t&&(t=new BigNumber(t)),BigNumber.config(r.ETH_BIGNUMBER_ROUNDING_MODE),t=t.round(),t.lessThan(0)&&(t=new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(t).plus(1)),t=t.toString(16)):t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?o(new BigNumber(t)):(+t).toString(16),i(t,e)},a=function(t){return n.fromAscii(t,r.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},s=function(t){return o(new BigNumber(t).times(new BigNumber(2).pow(128)))},f=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},c=function(t){return t=t||"0",f(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},l=function(t){return t=t||"0",new BigNumber(t,16)},p=function(t){return c(t).dividedBy(new BigNumber(2).pow(128))},m=function(t){return l(t).dividedBy(new BigNumber(2).pow(128))},h=function(t){return"0x"+t},d=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return n.toAscii(t)},v=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:o,formatInputString:a,formatInputBool:u,formatInputReal:s,formatOutputInt:c,formatOutputUInt:l,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:h,formatOutputBool:d,formatOutputString:g,formatOutputAddress:v}},{"./const":2,"./utils":12}],7:[function(t,e){var n=function(t){this.handlers=[],this.host=t||"http://localhost:8080"};n.prototype.send=function(t){var e=new XMLHttpRequest;e.open("POST",this.host,!1),e.send(JSON.stringify(t));var n=e.responseText;return JSON.parse(n)},e.exports=n},{}],8:[function(t,e){var n=1,r=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:n++}},i=function(t){return!(!t||t.error||"2.0"!==t.jsonrpc||"number"!=typeof t.id||!t.result&&"boolean"!=typeof t.result)},o=function(t){return t.map(function(t){return r(t.method,t.params)})};e.exports={toPayload:r,isValidResponse:i,toBatchPayload:o}},{}],9:[function(t,e){var n=(t("./web3"),t("./jsonrpc")),r=function(){this.polls=[],this.provider=void 0;var t=this,e=function(){if(t.provider){var r=t.polls.map(function(t){return t.data}),i=n.toBatchPayload(r),o=t.provider.send(i);t.polls.forEach(function(t,e){var r=o[e];return n.isValidResponse(r)?(r=r.result,void(r instanceof Array&&0!==r.length&&t.callback(r))):void console.log(r)})}setTimeout(e,1e3)};e()};r.prototype.send=function(t){var e=n.toPayload(t.method,t.params);if(void 0===this.provider)return console.error("provider is not set"),null;var r=this.provider.send(e);return n.isValidResponse(r)?r.result:(console.log(r),null)},r.prototype.set=function(t){this.provider=t},r.prototype.startPolling=function(t,e,n){this.polls.push({data:t,id:e,callback:n})},r.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},e.exports=r},{"./jsonrpc":8,"./web3":13}],10:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],11:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},i=function(t){return function(e){return t===e}},o=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("hash"),format:n.formatInputInt},{type:r("string"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:i("address"),format:n.formatInputInt},{type:i("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("hash"),format:n.formatOutputHash},{type:r("string"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:i("address"),format:n.formatOutputAddress},{type:i("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:i,inputTypes:o,outputTypes:a}},{"./formatters":6}],12:[function(t,e){var n=t("./const"),r=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},i=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},o=function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},a=function(t,e){e=void 0===e?0:e;for(var n=o(t);n.length<2*e;)n+="00";return"0x"+n},u=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},s=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)).replace(" ",""):""},f=function(t){return t.filter(function(t){return"function"===t.type})},c=function(t){return t.filter(function(t){return"event"===t.type})},l=function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,r=0,i=n.ETH_UNITS;e>3e3&&r<i.length-1;)e/=1e3,r++;for(var o=e.toString().length<e.toFixed(2).length?e.toString():e.toFixed(2),a=function(t,e,n){return e+","+n};;){var u=o;if(o=o.replace(/(\d)(\d\d\d[\.\,])/,a),u===o)break}return o+" "+i[r]};e.exports={findIndex:r,toAscii:i,fromAscii:a,extractDisplayName:u,extractTypeName:s,filterFunctions:f,filterEvents:c,toEth:l}},{"./const":2}],13:[function(t,e){var n=t("./utils"),r=function(){return[{name:"sha3",call:"web3_sha3"}]},i=function(){var t=function(t){return"string"==typeof t[0]?"eth_blockByHash":"eth_blockByNumber"},e=function(t){return"string"==typeof t[0]?"eth_transactionByHash":"eth_transactionByNumber"},n=function(t){return"string"==typeof t[0]?"eth_uncleByHash":"eth_uncleByNumber"},r=[{name:"balanceAt",call:"eth_balanceAt"},{name:"stateAt",call:"eth_stateAt"},{name:"storageAt",call:"eth_storageAt"},{name:"countAt",call:"eth_countAt"},{name:"codeAt",call:"eth_codeAt"},{name:"transact",call:"eth_transact"},{name:"call",call:"eth_call"},{name:"block",call:t},{name:"transaction",call:e},{name:"uncle",call:n},{name:"compilers",call:"eth_compilers"},{name:"flush",call:"eth_flush"},{name:"lll",call:"eth_lll"},{name:"solidity",call:"eth_solidity"},{name:"serpent",call:"eth_serpent"},{name:"logs",call:"eth_logs"}];return r},o=function(){return[{name:"coinbase",getter:"eth_coinbase",setter:"eth_setCoinbase"},{name:"listening",getter:"eth_listening",setter:"eth_setListening"},{name:"mining",getter:"eth_mining",setter:"eth_setMining"},{name:"gasPrice",getter:"eth_gasPrice"},{name:"accounts",getter:"eth_accounts"},{name:"peerCount",getter:"eth_peerCount"},{name:"defaultBlock",getter:"eth_defaultBlock",setter:"eth_setDefaultBlock"},{name:"number",getter:"eth_number"}]},a=function(){return[{name:"put",call:"db_put"},{name:"get",call:"db_get"},{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"}]},u=function(){return[{name:"post",call:"shh_post"},{name:"newIdentity",call:"shh_newIdentity"},{name:"haveIdentity",call:"shh_haveIdentity"},{name:"newGroup",call:"shh_newGroup"},{name:"addToGroup",call:"shh_addToGroup"}]},s=function(){var t=function(t){return"string"==typeof t[0]?"eth_newFilterString":"eth_newFilter"};return[{name:"newFilter",call:t},{name:"uninstallFilter",call:"eth_uninstallFilter"},{name:"getMessages",call:"eth_filterLogs"}]},f=function(){return[{name:"newFilter",call:"shh_newFilter"},{name:"uninstallFilter",call:"shh_uninstallFilter"},{name:"getMessages",call:"shh_getMessages"}]},c=function(t,e){e.forEach(function(e){t[e.name]=function(){var t=Array.prototype.slice.call(arguments),n="function"==typeof e.call?e.call(t):e.call;return p.provider.send({method:n,params:t})}})},l=function(t,e){e.forEach(function(e){var n={};n.get=function(){return p.provider.send({method:e.getter})},e.setter&&(n.set=function(t){return p.provider.send({method:e.setter,params:[t]})}),Object.defineProperty(t,e.name,n)})},p={_callbacks:{},_events:{},providers:{},toAscii:n.toAscii,fromAscii:n.fromAscii,toDecimal:function(t){return t=t.length>2?t.substring(2):"0",new BigNumber(t,16).toString(10)},fromDecimal:function(t){return"0x"+new BigNumber(t).toString(16)},toEth:n.toEth,eth:{contractFromAbi:function(t){return function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=p.eth.contract(e,t);return n.address=e,n}},watch:function(t,e,n){return t._isEvent?t(e,n):new p.filter(t,m)}},db:{},shh:{watch:function(t){return new p.filter(t,h)}}};c(p,r()),c(p.eth,i()),l(p.eth,o()),c(p.db,a()),c(p.shh,u());var m={changed:"eth_changed"};c(m,s());var h={changed:"shh_changed"};c(h,f()),p.setProvider=function(t){p.provider.set(t)},e.exports=p},{"./utils":12}],web3:[function(t,e){var n=t("./lib/web3"),r=t("./lib/providermanager");n.provider=new r,n.filter=t("./lib/filter"),n.providers.HttpSyncProvider=t("./lib/httpsync"),n.providers.QtSyncProvider=t("./lib/qtsync"),n.eth.contract=t("./lib/contract"),n.abi=t("./lib/abi"),e.exports=n},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"]); \ No newline at end of file diff --git a/libjsqrc/ethereumjs/example/event_inc.html b/libjsqrc/ethereumjs/example/event_inc.html new file mode 100644 index 000000000..17df9d681 --- /dev/null +++ b/libjsqrc/ethereumjs/example/event_inc.html @@ -0,0 +1,66 @@ +<!doctype> +<html> + <head> + <script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> + <script type="text/javascript" src="../dist/ethereum.js"></script> + <script type="text/javascript"> + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + + var source = "" + + "contract Contract { " + + " event Incremented(bool indexed odd, uint x); " + + " function Contract() { " + + " x = 69; " + + " } " + + " function inc() { " + + " ++x; " + + " Incremented(x % 2 == 1, x); " + + " } " + + " uint x; " + + "}"; + + var desc = [{ + "type":"event", + "name":"Incremented", + "inputs": [{"name":"odd","type":"bool","indexed":true},{"name":"x","type":"uint","indexed":false}], + }, { + "type":"function", + "name":"inc", + "inputs": [], + "outputs": [] + }]; + + var address; + var contract; + + var update = function (x) { + document.getElementById('result').innerText = JSON.stringify(x); + }; + + var createContract = function () { + address = web3.eth.transact({code: web3.eth.solidity(source)}); + contract = web3.eth.contract(address, desc); + contract.Incremented({odd: true}).changed(update); + + }; + + var callContract = function () { + contract.call().inc(); + }; + + + </script> + </head> + + <body> + <div> + <button type="button" onClick="createContract();">create contract</button> + </div> + <div> + <button type="button" onClick="callContract();">test1</button> + </div> + <div id="result"> + </div> + </body> +</html> diff --git a/libjsqrc/ethereumjs/lib/const.js b/libjsqrc/ethereumjs/lib/const.js index 22f6dc690..8a17b794d 100644 --- a/libjsqrc/ethereumjs/lib/const.js +++ b/libjsqrc/ethereumjs/lib/const.js @@ -25,9 +25,32 @@ if (process.env.NODE_ENV !== 'build') { var BigNumber = require('bignumber.js'); // jshint ignore:line } +var ETH_UNITS = [ + 'wei', + 'Kwei', + 'Mwei', + 'Gwei', + 'szabo', + 'finney', + 'ether', + 'grand', + 'Mether', + 'Gether', + 'Tether', + 'Pether', + 'Eether', + 'Zether', + 'Yether', + 'Nether', + 'Dether', + 'Vether', + 'Uether' +]; + module.exports = { ETH_PADDING: 32, ETH_SIGNATURE_LENGTH: 4, + ETH_UNITS: ETH_UNITS, ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } }; diff --git a/libjsqrc/ethereumjs/lib/contract.js b/libjsqrc/ethereumjs/lib/contract.js index 748844fec..a0525bd9d 100644 --- a/libjsqrc/ethereumjs/lib/contract.js +++ b/libjsqrc/ethereumjs/lib/contract.js @@ -120,6 +120,11 @@ var addFunctionsToContract = function (contract, desc, address) { var addEventRelatedPropertiesToContract = function (contract, desc, address) { contract.address = address; + contract._onWatchEventResult = function (data) { + var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc)); + var parser = eventImpl.outputParser(matchingEvent); + return parser(data); + }; Object.defineProperty(contract, 'topic', { get: function() { @@ -138,8 +143,12 @@ var addEventsToContract = function (contract, desc, address) { var impl = function () { var params = Array.prototype.slice.call(arguments); var signature = abi.eventSignatureFromAscii(e.name); - var event = eventImpl(address, signature, e); + var event = eventImpl.inputParser(address, signature, e); var o = event.apply(null, params); + o._onWatchEventResult = function (data) { + var parser = eventImpl.outputParser(e); + return parser(data); + }; return web3.eth.watch(o); }; diff --git a/libjsqrc/ethereumjs/lib/event.js b/libjsqrc/ethereumjs/lib/event.js index 812ef9115..0c41e0a39 100644 --- a/libjsqrc/ethereumjs/lib/event.js +++ b/libjsqrc/ethereumjs/lib/event.js @@ -23,6 +23,16 @@ var abi = require('./abi'); var utils = require('./utils'); +/// filter inputs array && returns only indexed (or not) inputs +/// @param inputs array +/// @param bool if result should be an array of indexed params on not +/// @returns array of (not?) indexed params +var filterInputs = function (inputs, indexed) { + return inputs.filter(function (current) { + return current.indexed === indexed; + }); +}; + var inputWithName = function (inputs, name) { var index = utils.findIndex(inputs, function (input) { return input.name === name; @@ -38,7 +48,7 @@ var inputWithName = function (inputs, name) { var indexedParamsToTopics = function (event, indexed) { // sort keys? return Object.keys(indexed).map(function (key) { - var inputs = [inputWithName(event.inputs, key)]; + var inputs = [inputWithName(filterInputs(event.inputs, true), key)]; var value = indexed[key]; if (value instanceof Array) { @@ -50,7 +60,7 @@ var indexedParamsToTopics = function (event, indexed) { }); }; -var implementationOfEvent = function (address, signature, event) { +var inputParser = function (address, signature, event) { // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' return function (indexed, options) { @@ -65,5 +75,61 @@ var implementationOfEvent = function (address, signature, event) { }; }; -module.exports = implementationOfEvent; +var getArgumentsObject = function (inputs, indexed, notIndexed) { + var indexedCopy = indexed.slice(); + var notIndexedCopy = notIndexed.slice(); + return inputs.reduce(function (acc, current) { + var value; + if (current.indexed) + value = indexed.splice(0, 1)[0]; + else + value = notIndexed.splice(0, 1)[0]; + + acc[current.name] = value; + return acc; + }, {}); +}; + +var outputParser = function (event) { + + return function (output) { + var result = { + event: utils.extractDisplayName(event.name), + number: output.number, + args: {} + }; + + if (!output.topic) { + return result; + } + + var indexedOutputs = filterInputs(event.inputs, true); + var indexedData = "0x" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join(""); + var indexedRes = abi.formatOutput(indexedOutputs, indexedData); + + var notIndexedOutputs = filterInputs(event.inputs, false); + var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data); + + result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes); + + return result; + }; +}; + +var getMatchingEvent = function (events, payload) { + for (var i = 0; i < events.length; i++) { + var signature = abi.eventSignatureFromAscii(events[i].name); + if (signature === payload.topic[0]) { + return events[i]; + } + } + return undefined; +}; + + +module.exports = { + inputParser: inputParser, + outputParser: outputParser, + getMatchingEvent: getMatchingEvent +}; diff --git a/libjsqrc/ethereumjs/lib/filter.js b/libjsqrc/ethereumjs/lib/filter.js index 25b6d9a4a..6ab2b7edc 100644 --- a/libjsqrc/ethereumjs/lib/filter.js +++ b/libjsqrc/ethereumjs/lib/filter.js @@ -36,6 +36,8 @@ var Filter = function(options, impl) { if (options.topics) { console.warn('"topics" is deprecated, use "topic" instead'); } + + this._onWatchResult = options._onWatchEventResult; // evaluate lazy properties options = { @@ -54,7 +56,7 @@ var Filter = function(options, impl) { this.callbacks = []; this.id = impl.newFilter(options); - web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); + web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this)); }; /// alias for changed* @@ -74,7 +76,8 @@ Filter.prototype.changed = function(callback) { Filter.prototype.trigger = function(messages) { for (var i = 0; i < this.callbacks.length; i++) { for (var j = 0; j < messages.length; j++) { - this.callbacks[i].call(this, messages[j]); + var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j]; + this.callbacks[i].call(this, message); } } }; diff --git a/libjsqrc/ethereumjs/lib/httpsync.js b/libjsqrc/ethereumjs/lib/httpsync.js index a638cfe94..06e410ca8 100644 --- a/libjsqrc/ethereumjs/lib/httpsync.js +++ b/libjsqrc/ethereumjs/lib/httpsync.js @@ -30,40 +30,16 @@ var HttpSyncProvider = function (host) { this.host = host || 'http://localhost:8080'; }; -/// Transforms inner message to proper jsonrpc object -/// @param inner message object -/// @returns jsonrpc object -function formatJsonRpcObject(object) { - return { - jsonrpc: '2.0', - method: object.call, - params: object.args, - id: object._id - }; -} - -/// Transforms jsonrpc object to inner message -/// @param incoming jsonrpc message -/// @returns inner message object -function formatJsonRpcMessage(message) { - var object = JSON.parse(message); - - return { - _id: object.id, - data: object.result, - error: object.error - }; -} - HttpSyncProvider.prototype.send = function (payload) { - var data = formatJsonRpcObject(payload); + //var data = formatJsonRpcObject(payload); var request = new XMLHttpRequest(); request.open('POST', this.host, false); - request.send(JSON.stringify(data)); + request.send(JSON.stringify(payload)); // check request.status - return request.responseText; + var result = request.responseText; + return JSON.parse(result); }; module.exports = HttpSyncProvider; diff --git a/libjsqrc/ethereumjs/lib/jsonrpc.js b/libjsqrc/ethereumjs/lib/jsonrpc.js new file mode 100644 index 000000000..63afa3229 --- /dev/null +++ b/libjsqrc/ethereumjs/lib/jsonrpc.js @@ -0,0 +1,65 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file jsonrpc.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * @date 2015 + */ + +var messageId = 1; + +/// Should be called to valid json create payload object +/// @param method of jsonrpc call, required +/// @param params, an array of method params, optional +/// @returns valid jsonrpc payload object +var toPayload = function (method, params) { + if (!method) + console.error('jsonrpc method should be specified!'); + + return { + jsonrpc: '2.0', + method: method, + params: params || [], + id: messageId++ + }; +}; + +/// Should be called to check if jsonrpc response is valid +/// @returns true if response is valid, otherwise false +var isValidResponse = function (response) { + return !!response && + !response.error && + response.jsonrpc === '2.0' && + typeof response.id === 'number' && + (!!response.result || typeof response.result === 'boolean'); +}; + +/// Should be called to create batch payload object +/// @param messages, an array of objects with method (required) and params (optional) fields +var toBatchPayload = function (messages) { + return messages.map(function (message) { + return toPayload(message.method, message.params); + }); +}; + +module.exports = { + toPayload: toPayload, + isValidResponse: isValidResponse, + toBatchPayload: toBatchPayload +}; + + diff --git a/libjsqrc/ethereumjs/lib/providermanager.js b/libjsqrc/ethereumjs/lib/providermanager.js index 25cd14288..55f166bcd 100644 --- a/libjsqrc/ethereumjs/lib/providermanager.js +++ b/libjsqrc/ethereumjs/lib/providermanager.js @@ -23,7 +23,9 @@ * @date 2014 */ -var web3 = require('./web3'); // jshint ignore:line +var web3 = require('./web3'); +var jsonrpc = require('./jsonrpc'); + /** * Provider manager object prototype @@ -37,25 +39,35 @@ var web3 = require('./web3'); // jshint ignore:line var ProviderManager = function() { this.polls = []; this.provider = undefined; - this.id = 1; var self = this; var poll = function () { if (self.provider) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - var result = self.provider.send(data.data); - - result = JSON.parse(result); + var pollsBatch = self.polls.map(function (data) { + return data.data; + }); + + var payload = jsonrpc.toBatchPayload(pollsBatch); + var results = self.provider.send(payload); + + self.polls.forEach(function (data, index) { + var result = results[index]; + if (!jsonrpc.isValidResponse(result)) { + console.log(result); + return; + } + + result = result.result; // dont call the callback if result is not an array, or empty one - if (result.error || !(result.result instanceof Array) || result.result.length === 0) { + if (!(result instanceof Array) || result.length === 0) { return; } - data.callback(result.result); + data.callback(result); + }); + } setTimeout(poll, 1000); }; @@ -63,22 +75,19 @@ var ProviderManager = function() { }; /// sends outgoing requests +/// @params data - an object with at least 'method' property ProviderManager.prototype.send = function(data) { - - data.args = data.args || []; - data._id = this.id++; + var payload = jsonrpc.toPayload(data.method, data.params); if (this.provider === undefined) { console.error('provider is not set'); return null; } - //TODO: handle error here? - var result = this.provider.send(data); - result = JSON.parse(result); + var result = this.provider.send(payload); - if (result.error) { - console.log(result.error); + if (!jsonrpc.isValidResponse(result)) { + console.log(result); return null; } diff --git a/libjsqrc/ethereumjs/lib/qtsync.js b/libjsqrc/ethereumjs/lib/qtsync.js index a287a7172..75dcb43ab 100644 --- a/libjsqrc/ethereumjs/lib/qtsync.js +++ b/libjsqrc/ethereumjs/lib/qtsync.js @@ -25,7 +25,8 @@ var QtSyncProvider = function () { }; QtSyncProvider.prototype.send = function (payload) { - return navigator.qt.callMethod(JSON.stringify(payload)); + var result = navigator.qt.callMethod(JSON.stringify(payload)); + return JSON.parse(result); }; module.exports = QtSyncProvider; diff --git a/libjsqrc/ethereumjs/lib/utils.js b/libjsqrc/ethereumjs/lib/utils.js index 5cd6ec8d6..7cc1917e1 100644 --- a/libjsqrc/ethereumjs/lib/utils.js +++ b/libjsqrc/ethereumjs/lib/utils.js @@ -20,6 +20,8 @@ * @date 2015 */ +var c = require('./const'); + /// Finds first index of array element matching pattern /// @param array /// @param callback pattern @@ -82,7 +84,7 @@ var extractDisplayName = function (name) { var extractTypeName = function (name) { /// TODO: make it invulnerable var length = name.indexOf('('); - return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : ""; + return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : ""; }; /// Filters all function from input abi @@ -101,6 +103,32 @@ var filterEvents = function (json) { }); }; +/// used to transform value/string to eth string +/// TODO: use BigNumber.js to parse int +/// TODO: add tests for it! +var toEth = function (str) { + var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; + var unit = 0; + var units = c.ETH_UNITS; + while (val > 3000 && unit < units.length - 1) + { + val /= 1000; + unit++; + } + var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); + var replaceFunction = function($0, $1, $2) { + return $1 + ',' + $2; + }; + + while (true) { + var o = s; + s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); + if (o === s) + break; + } + return s + ' ' + units[unit]; +}; + module.exports = { findIndex: findIndex, toAscii: toAscii, @@ -108,6 +136,7 @@ module.exports = { extractDisplayName: extractDisplayName, extractTypeName: extractTypeName, filterFunctions: filterFunctions, - filterEvents: filterEvents + filterEvents: filterEvents, + toEth: toEth }; diff --git a/libjsqrc/ethereumjs/lib/web3.js b/libjsqrc/ethereumjs/lib/web3.js index c3126afc4..41df75051 100644 --- a/libjsqrc/ethereumjs/lib/web3.js +++ b/libjsqrc/ethereumjs/lib/web3.js @@ -29,28 +29,6 @@ if (process.env.NODE_ENV !== 'build') { var utils = require('./utils'); -var ETH_UNITS = [ - 'wei', - 'Kwei', - 'Mwei', - 'Gwei', - 'szabo', - 'finney', - 'ether', - 'grand', - 'Mether', - 'Gether', - 'Tether', - 'Pether', - 'Eether', - 'Zether', - 'Yether', - 'Nether', - 'Dether', - 'Vether', - 'Uether' -]; - /// @returns an array of objects describing web3 api methods var web3Methods = function () { return [ @@ -158,8 +136,8 @@ var setupMethods = function (obj, methods) { var args = Array.prototype.slice.call(arguments); var call = typeof method.call === 'function' ? method.call(args) : method.call; return web3.provider.send({ - call: call, - args: args + method: call, + params: args }); }; }); @@ -172,15 +150,15 @@ var setupProperties = function (obj, properties) { var proto = {}; proto.get = function () { return web3.provider.send({ - call: property.getter + method: property.getter }); }; if (property.setter) { proto.set = function (val) { return web3.provider.send({ - call: property.setter, - args: [val] + method: property.setter, + params: [val] }); }; } @@ -213,29 +191,7 @@ var web3 = { }, /// used to transform value/string to eth string - /// TODO: use BigNumber.js to parse int - toEth: function(str) { - var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; - var unit = 0; - var units = ETH_UNITS; - while (val > 3000 && unit < units.length - 1) - { - val /= 1000; - unit++; - } - var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); - var replaceFunction = function($0, $1, $2) { - return $1 + ',' + $2; - }; - - while (true) { - var o = s; - s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); - if (o === s) - break; - } - return s + ' ' + units[unit]; - }, + toEth: utils.toEth, /// eth object prototype eth: { @@ -271,11 +227,6 @@ var web3 = { return new web3.filter(filter, shhWatch); } }, - - /// @returns true if provider is installed - haveProvider: function() { - return !!web3.provider.provider; - } }; /// setups all api methods @@ -298,7 +249,6 @@ var shhWatch = { setupMethods(shhWatch, shhWatchMethods()); web3.setProvider = function(provider) { - //provider.onmessage = messageHandler; // there will be no async calls, to remove web3.provider.set(provider); }; diff --git a/libjsqrc/ethereumjs/package.json b/libjsqrc/ethereumjs/package.json index a61ffc76a..8102a2592 100644 --- a/libjsqrc/ethereumjs/package.json +++ b/libjsqrc/ethereumjs/package.json @@ -1,7 +1,7 @@ { "name": "ethereum.js", "namespace": "ethereum", - "version": "0.0.11", + "version": "0.0.13", "description": "Ethereum Compatible JavaScript API", "main": "./index.js", "directories": { diff --git a/libjsqrc/ethereumjs/test/abi.parsers.js b/libjsqrc/ethereumjs/test/abi.inputParser.js similarity index 52% rename from libjsqrc/ethereumjs/test/abi.parsers.js rename to libjsqrc/ethereumjs/test/abi.inputParser.js index 12bccf5a5..12b735153 100644 --- a/libjsqrc/ethereumjs/test/abi.parsers.js +++ b/libjsqrc/ethereumjs/test/abi.inputParser.js @@ -423,443 +423,5 @@ describe('abi', function() { }); }); - - describe('outputParser', function() { - it('should parse output string', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: "string" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], - 'hello' - ); - assert.equal( - parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "776f726c64000000000000000000000000000000000000000000000000000000")[0], - 'world' - ); - - }); - - it('should parse output uint', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output uint256', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint256' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output uint128', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint128' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output int', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output int256', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int256' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output int128', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int128' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output hash', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'hash' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], - "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" - ); - }); - - it('should parse output hash256', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'hash256' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], - "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" - ); - }); - - it('should parse output hash160', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'hash160' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], - "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" - ); - // TODO shouldnt' the expected hash be shorter? - }); - - it('should parse output address', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'address' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], - "0x407d73d8a49eeb85d32cf465507dd71d507100c1" - ); - }); - - it('should parse output bool', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'bool' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true); - assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false); - - - }); - - it('should parse output real', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'real' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); - assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); - assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); - assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1); - - }); - - it('should parse output ureal', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'ureal' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); - assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); - assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); - - }); - - - it('should parse multiple output strings', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: "string" }, - { type: "string" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" + - "776f726c64000000000000000000000000000000000000000000000000000000")[0], - 'hello' - ); - assert.equal( - parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" + - "776f726c64000000000000000000000000000000000000000000000000000000")[1], - 'world' - ); - - }); - - it('should use proper method name', function () { - - // given - var d = clone(description); - d[0].name = 'helloworld(int)'; - d[0].outputs = [ - { type: "int" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - - }); - - - it('should parse multiple methods', function () { - - // given - var d = [{ - name: "test", - type: "function", - inputs: [{ type: "int" }], - outputs: [{ type: "int" }] - },{ - name: "test2", - type: "function", - inputs: [{ type: "string" }], - outputs: [{ type: "string" }] - }]; - - // when - var parser = abi.outputParser(d); - - //then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test2("0x" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], - "hello" - ); - - }); - - it('should parse output array', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'int[]' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006")[0][0], - 5 - ); - assert.equal(parser.test("0x" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006")[0][1], - 6 - ); - - }); - - it('should parse 0x value', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'int' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x")[0], 0); - - }); - - it('should parse 0x value', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'uint' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x")[0], 0); - - }); - - }); }); diff --git a/libjsqrc/ethereumjs/test/abi.outputParser.js b/libjsqrc/ethereumjs/test/abi.outputParser.js new file mode 100644 index 000000000..723c408f0 --- /dev/null +++ b/libjsqrc/ethereumjs/test/abi.outputParser.js @@ -0,0 +1,461 @@ +var assert = require('assert'); +var BigNumber = require('bignumber.js'); +var abi = require('../lib/abi.js'); +var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; + +var description = [{ + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] +}]; + +describe('abi', function() { + describe('outputParser', function() { + it('should parse output string', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], + 'hello' + ); + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "776f726c64000000000000000000000000000000000000000000000000000000")[0], + 'world' + ); + + }); + + it('should parse output uint', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); + }); + + it('should parse output uint256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); + }); + + it('should parse output uint128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); + }); + + it('should parse output int', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); + }); + + it('should parse output int256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); + }); + + it('should parse output int128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); + }); + + it('should parse output hash', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); + }); + + it('should parse output hash256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); + }); + + it('should parse output hash160', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash160' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); + // TODO shouldnt' the expected hash be shorter? + }); + + it('should parse output address', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'address' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x407d73d8a49eeb85d32cf465507dd71d507100c1" + ); + }); + + it('should parse output bool', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true); + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false); + + + }); + + it('should parse output real', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'real' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); + assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); + assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1); + + }); + + it('should parse output ureal', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'ureal' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); + assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); + assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); + + }); + + + it('should parse multiple output strings', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" }, + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + + "776f726c64000000000000000000000000000000000000000000000000000000")[0], + 'hello' + ); + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + + "776f726c64000000000000000000000000000000000000000000000000000000")[1], + 'world' + ); + + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld(int)'; + d[0].outputs = [ + { type: "int" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + + }); + + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + type: "function", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + type: "function", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] + }]; + + // when + var parser = abi.outputParser(d); + + //then + assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test2("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], + "hello" + ); + + }); + + it('should parse output array', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'int[]' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006")[0][0], + 5 + ); + assert.equal(parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006")[0][1], + 6 + ); + + }); + + it('should parse 0x value', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'int' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x")[0], 0); + + }); + + it('should parse 0x value', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'uint' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x")[0], 0); + + }); + + }); +}); + diff --git a/libjsqrc/ethereumjs/test/db.methods.js b/libjsqrc/ethereumjs/test/db.methods.js index 8f8f5409f..2ad384579 100644 --- a/libjsqrc/ethereumjs/test/db.methods.js +++ b/libjsqrc/ethereumjs/test/db.methods.js @@ -1,7 +1,7 @@ var assert = require('assert'); var web3 = require('../index.js'); -var u = require('./utils.js'); +var u = require('./test.utils.js'); describe('web3', function() { describe('db', function() { diff --git a/libjsqrc/ethereumjs/test/eth.methods.js b/libjsqrc/ethereumjs/test/eth.methods.js index 7a031c4c8..8f10b441d 100644 --- a/libjsqrc/ethereumjs/test/eth.methods.js +++ b/libjsqrc/ethereumjs/test/eth.methods.js @@ -1,6 +1,6 @@ var assert = require('assert'); var web3 = require('../index.js'); -var u = require('./utils.js'); +var u = require('./test.utils.js'); describe('web3', function() { describe('eth', function() { diff --git a/libjsqrc/ethereumjs/test/event.inputParser.js b/libjsqrc/ethereumjs/test/event.inputParser.js new file mode 100644 index 000000000..8f9790a2d --- /dev/null +++ b/libjsqrc/ethereumjs/test/event.inputParser.js @@ -0,0 +1,125 @@ +var assert = require('assert'); +var event = require('../lib/event.js'); +var f = require('../lib/formatters.js'); + +describe('event', function () { + describe('inputParser', function () { + it('should create basic filter input object', function () { + + // given + var address = '0x012345'; + var signature = '0x987654'; + var e = { + name: 'Event', + inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] + }; + + // when + var impl = event.inputParser(address, signature, e); + var result = impl(); + + // then + assert.equal(result.address, address); + assert.equal(result.topic.length, 1); + assert.equal(result.topic[0], signature); + + }); + + it('should create filter input object with options', function () { + + // given + var address = '0x012345'; + var signature = '0x987654'; + var options = { + earliest: 1, + latest: 2, + offset: 3, + max: 4 + }; + var e = { + name: 'Event', + inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] + }; + + // when + var impl = event.inputParser(address, signature, e); + var result = impl({}, options); + + // then + assert.equal(result.address, address); + assert.equal(result.topic.length, 1); + assert.equal(result.topic[0], signature); + assert.equal(result.earliest, options.earliest); + assert.equal(result.latest, options.latest); + assert.equal(result.offset, options.offset); + assert.equal(result.max, options.max); + + }); + + it('should create filter input object with indexed params', function () { + + // given + var address = '0x012345'; + var signature = '0x987654'; + var options = { + earliest: 1, + latest: 2, + offset: 3, + max: 4 + }; + var e = { + name: 'Event', + inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] + }; + + // when + var impl = event.inputParser(address, signature, e); + var result = impl({a: 4}, options); + + // then + assert.equal(result.address, address); + assert.equal(result.topic.length, 2); + assert.equal(result.topic[0], signature); + assert.equal(result.topic[1], f.formatInputInt(4)); + assert.equal(result.earliest, options.earliest); + assert.equal(result.latest, options.latest); + assert.equal(result.offset, options.offset); + assert.equal(result.max, options.max); + + }); + + it('should create filter input object with an array of indexed params', function () { + + // given + var address = '0x012345'; + var signature = '0x987654'; + var options = { + earliest: 1, + latest: 2, + offset: 3, + max: 4 + }; + var e = { + name: 'Event', + inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] + }; + + // when + var impl = event.inputParser(address, signature, e); + var result = impl({a: [4, 69]}, options); + + // then + assert.equal(result.address, address); + assert.equal(result.topic.length, 2); + assert.equal(result.topic[0], signature); + assert.equal(result.topic[1][0], f.formatInputInt(4)); + assert.equal(result.topic[1][1], f.formatInputInt(69)); + assert.equal(result.earliest, options.earliest); + assert.equal(result.latest, options.latest); + assert.equal(result.offset, options.offset); + assert.equal(result.max, options.max); + + }); + }); +}); + diff --git a/libjsqrc/ethereumjs/test/event.js b/libjsqrc/ethereumjs/test/event.js deleted file mode 100644 index 9edd93ae7..000000000 --- a/libjsqrc/ethereumjs/test/event.js +++ /dev/null @@ -1,124 +0,0 @@ -var assert = require('assert'); -var event = require('../lib/event.js'); -var f = require('../lib/formatters.js'); - -describe('event', function () { - it('should create basic filter input object', function () { - - // given - var address = '0x012345'; - var signature = '0x987654'; - var e = { - name: 'Event', - inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] - }; - - // when - var impl = event(address, signature, e); - var result = impl(); - - // then - assert.equal(result.address, address); - assert.equal(result.topic.length, 1); - assert.equal(result.topic[0], signature); - - }); - - it('should create filter input object with options', function () { - - // given - var address = '0x012345'; - var signature = '0x987654'; - var options = { - earliest: 1, - latest: 2, - offset: 3, - max: 4 - }; - var e = { - name: 'Event', - inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] - }; - - // when - var impl = event(address, signature, e); - var result = impl({}, options); - - // then - assert.equal(result.address, address); - assert.equal(result.topic.length, 1); - assert.equal(result.topic[0], signature); - assert.equal(result.earliest, options.earliest); - assert.equal(result.latest, options.latest); - assert.equal(result.offset, options.offset); - assert.equal(result.max, options.max); - - }); - - it('should create filter input object with indexed params', function () { - - // given - var address = '0x012345'; - var signature = '0x987654'; - var options = { - earliest: 1, - latest: 2, - offset: 3, - max: 4 - }; - var e = { - name: 'Event', - inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] - }; - - // when - var impl = event(address, signature, e); - var result = impl({a: 4}, options); - - // then - assert.equal(result.address, address); - assert.equal(result.topic.length, 2); - assert.equal(result.topic[0], signature); - assert.equal(result.topic[1], f.formatInputInt(4)); - assert.equal(result.earliest, options.earliest); - assert.equal(result.latest, options.latest); - assert.equal(result.offset, options.offset); - assert.equal(result.max, options.max); - - }); - - it('should create filter input object with an array of indexed params', function () { - - // given - var address = '0x012345'; - var signature = '0x987654'; - var options = { - earliest: 1, - latest: 2, - offset: 3, - max: 4 - }; - var e = { - name: 'Event', - inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] - }; - - // when - var impl = event(address, signature, e); - var result = impl({a: [4, 69]}, options); - - // then - assert.equal(result.address, address); - assert.equal(result.topic.length, 2); - assert.equal(result.topic[0], signature); - assert.equal(result.topic[1][0], f.formatInputInt(4)); - assert.equal(result.topic[1][1], f.formatInputInt(69)); - assert.equal(result.earliest, options.earliest); - assert.equal(result.latest, options.latest); - assert.equal(result.offset, options.offset); - assert.equal(result.max, options.max); - - }); - -}); - diff --git a/libjsqrc/ethereumjs/test/event.outputParser.js b/libjsqrc/ethereumjs/test/event.outputParser.js new file mode 100644 index 000000000..22f4ed395 --- /dev/null +++ b/libjsqrc/ethereumjs/test/event.outputParser.js @@ -0,0 +1,81 @@ +var assert = require('assert'); +var event = require('../lib/event.js'); + +describe('event', function () { + describe('outputParser', function () { + it('should parse basic event output object', function () { + + // given + var output = { + "address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e", + "data":"0x000000000000000000000000000000000000000000000000000000000000004b", + "number":2, + "topic":[ + "0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ] + }; + + var e = { + name: 'Event', + inputs: [{"name":"a","type":"bool","indexed":true},{"name":"b","type":"uint256","indexed":false}] + }; + + // when + var impl = event.outputParser(e); + var result = impl(output); + + // then + assert.equal(result.event, 'Event'); + assert.equal(result.number, 2); + assert.equal(Object.keys(result.args).length, 2); + assert.equal(result.args.a, true); + assert.equal(result.args.b, 75); + }); + + it('should parse event output object arguments in correct order', function () { + + // given + var output = { + "address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e", + "data": "0x" + + "000000000000000000000000000000000000000000000000000000000000004b" + + "000000000000000000000000000000000000000000000000000000000000004c" + + "0000000000000000000000000000000000000000000000000000000000000001", + "number":3, + "topic":[ + "0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000005" + ] + }; + + var e = { + name: 'Event2', + inputs: [ + {"name":"a","type":"bool","indexed":true}, + {"name":"b","type":"int","indexed":false}, + {"name":"c","type":"int","indexed":false}, + {"name":"d","type":"int","indexed":true}, + {"name":"e","type":"bool","indexed":false} + ] + }; + + // when + var impl = event.outputParser(e); + var result = impl(output); + + // then + assert.equal(result.event, 'Event2'); + assert.equal(result.number, 3); + assert.equal(Object.keys(result.args).length, 5); + assert.equal(result.args.a, true); + assert.equal(result.args.b, 75); + assert.equal(result.args.c, 76); + assert.equal(result.args.d, 5); + assert.equal(result.args.e, true); + + }); + }); +}); + diff --git a/libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js b/libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js new file mode 100644 index 000000000..2fe200496 --- /dev/null +++ b/libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js @@ -0,0 +1,128 @@ +var assert = require('assert'); +var jsonrpc = require('../lib/jsonrpc'); + +describe('jsonrpc', function () { + describe('isValidResponse', function () { + it('should validate basic jsonrpc response', function () { + + // given + var response = { + jsonrpc: '2.0', + id: 1, + result: [] + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, true); + }); + + it('should validate basic undefined response', function () { + + // given + var response = undefined; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response without jsonrpc field', function () { + + // given + var response = { + id: 1, + result: [] + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response with wrong jsonrpc version', function () { + + // given + var response = { + jsonrpc: '1.0', + id: 1, + result: [] + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response without id number', function () { + + // given + var response = { + jsonrpc: '2.0', + result: [] + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response with wrong id field', function () { + + // given + var response = { + jsonrpc: '2.0', + id: 'x', + result: [] + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response without result field', function () { + + // given + var response = { + jsonrpc: '2.0', + id: 1 + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, false); + }); + + it('should validate jsonrpc response with result field === false', function () { + + // given + var response = { + jsonrpc: '2.0', + id: 1, + result: false + }; + + // when + var valid = jsonrpc.isValidResponse(response); + + // then + assert.equal(valid, true); + }); + + }); +}); diff --git a/libjsqrc/ethereumjs/test/jsonrpc.toBatchPayload.js b/libjsqrc/ethereumjs/test/jsonrpc.toBatchPayload.js new file mode 100644 index 000000000..1c1aafebb --- /dev/null +++ b/libjsqrc/ethereumjs/test/jsonrpc.toBatchPayload.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var jsonrpc = require('../lib/jsonrpc'); + +describe('jsonrpc', function () { + describe('toBatchPayload', function () { + it('should create basic batch payload', function () { + + // given + var messages = [{ + method: 'helloworld' + }, { + method: 'test2', + params: [1] + }]; + + // when + var payload = jsonrpc.toBatchPayload(messages); + + // then + assert.equal(payload instanceof Array, true); + assert.equal(payload.length, 2); + assert.equal(payload[0].jsonrpc, '2.0'); + assert.equal(payload[1].jsonrpc, '2.0'); + assert.equal(payload[0].method, 'helloworld'); + assert.equal(payload[1].method, 'test2'); + assert.equal(payload[0].params instanceof Array, true); + assert.equal(payload[1].params.length, 1); + assert.equal(payload[1].params[0], 1); + assert.equal(typeof payload[0].id, 'number'); + assert.equal(typeof payload[1].id, 'number'); + assert.equal(payload[0].id + 1, payload[1].id); + }); + + it('should create batch payload for empty input array', function () { + + // given + var messages = []; + + // when + var payload = jsonrpc.toBatchPayload(messages); + + // then + assert.equal(payload instanceof Array, true); + assert.equal(payload.length, 0); + }); + }); +}); diff --git a/libjsqrc/ethereumjs/test/jsonrpc.toPayload.js b/libjsqrc/ethereumjs/test/jsonrpc.toPayload.js new file mode 100644 index 000000000..6d6f003bb --- /dev/null +++ b/libjsqrc/ethereumjs/test/jsonrpc.toPayload.js @@ -0,0 +1,40 @@ +var assert = require('assert'); +var jsonrpc = require('../lib/jsonrpc'); + +describe('jsonrpc', function () { + describe('toPayload', function () { + it('should create basic payload', function () { + + // given + var method = 'helloworld'; + + // when + var payload = jsonrpc.toPayload(method); + + // then + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, method); + assert.equal(payload.params instanceof Array, true); + assert.equal(payload.params.length, 0); + assert.equal(typeof payload.id, 'number'); + }); + + it('should create payload with params', function () { + + // given + var method = 'helloworld1'; + var params = [123, 'test']; + + // when + var payload = jsonrpc.toPayload(method, params); + + // then + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, method); + assert.equal(payload.params.length, 2); + assert.equal(payload.params[0], params[0]); + assert.equal(payload.params[1], params[1]); + assert.equal(typeof payload.id, 'number'); + }); + }); +}); diff --git a/libjsqrc/ethereumjs/test/shh.methods.js b/libjsqrc/ethereumjs/test/shh.methods.js index fe2dae71d..91ca3caba 100644 --- a/libjsqrc/ethereumjs/test/shh.methods.js +++ b/libjsqrc/ethereumjs/test/shh.methods.js @@ -1,6 +1,6 @@ var assert = require('assert'); var web3 = require('../index.js'); -var u = require('./utils.js'); +var u = require('./test.utils.js'); describe('web3', function() { describe('shh', function() { diff --git a/libjsqrc/ethereumjs/test/utils.js b/libjsqrc/ethereumjs/test/test.utils.js similarity index 100% rename from libjsqrc/ethereumjs/test/utils.js rename to libjsqrc/ethereumjs/test/test.utils.js diff --git a/libjsqrc/ethereumjs/test/utils.extractDisplayName.js b/libjsqrc/ethereumjs/test/utils.extractDisplayName.js new file mode 100644 index 000000000..148653ab2 --- /dev/null +++ b/libjsqrc/ethereumjs/test/utils.extractDisplayName.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var utils = require('../lib/utils.js'); + +describe('utils', function () { + describe('extractDisplayName', function () { + it('should extract display name from method with no params', function () { + + // given + var test = 'helloworld()'; + + // when + var displayName = utils.extractDisplayName(test); + + // then + assert.equal(displayName, 'helloworld'); + }); + + it('should extract display name from method with one param' , function () { + + // given + var test = 'helloworld1(int)'; + + // when + var displayName = utils.extractDisplayName(test); + + // then + assert.equal(displayName, 'helloworld1'); + }); + + it('should extract display name from method with two params' , function () { + + // given + var test = 'helloworld2(int,string)'; + + // when + var displayName = utils.extractDisplayName(test); + + // then + assert.equal(displayName, 'helloworld2'); + }); + }); +}); diff --git a/libjsqrc/ethereumjs/test/utils.extractTypeName.js b/libjsqrc/ethereumjs/test/utils.extractTypeName.js new file mode 100644 index 000000000..2b4bbe767 --- /dev/null +++ b/libjsqrc/ethereumjs/test/utils.extractTypeName.js @@ -0,0 +1,55 @@ +var assert = require('assert'); +var utils = require('../lib/utils.js'); + +describe('utils', function () { + describe('extractTypeName', function () { + it('should extract type name from method with no params', function () { + + // given + var test = 'helloworld()'; + + // when + var typeName = utils.extractTypeName(test); + + // then + assert.equal(typeName, ''); + }); + + it('should extract type name from method with one param', function () { + + // given + var test = 'helloworld1(int)'; + + // when + var typeName = utils.extractTypeName(test); + + // then + assert.equal(typeName, 'int'); + }); + + it('should extract type name from method with two params', function () { + + // given + var test = 'helloworld2(int,string)'; + + // when + var typeName = utils.extractTypeName(test); + + // then + assert.equal(typeName, 'int,string'); + }); + + it('should extract type name from method with spaces between params', function () { + + // given + var test = 'helloworld3(int, string)'; + + // when + var typeName = utils.extractTypeName(test); + + // then + assert.equal(typeName, 'int,string'); + }); + + }); +}); diff --git a/libjsqrc/ethereumjs/test/web3.methods.js b/libjsqrc/ethereumjs/test/web3.methods.js index d08495dd9..06de41da4 100644 --- a/libjsqrc/ethereumjs/test/web3.methods.js +++ b/libjsqrc/ethereumjs/test/web3.methods.js @@ -1,6 +1,6 @@ var assert = require('assert'); var web3 = require('../index.js'); -var u = require('./utils.js'); +var u = require('./test.utils.js'); describe('web3', function() { u.methodExists(web3, 'sha3'); diff --git a/libqwebthree/QWebThree.cpp b/libqwebthree/QWebThree.cpp index 804766563..31f2f6b92 100644 --- a/libqwebthree/QWebThree.cpp +++ b/libqwebthree/QWebThree.cpp @@ -41,20 +41,9 @@ void QWebThree::clientDieing() this->disconnect(); } -static QString formatInput(QJsonObject const& _object) -{ - QJsonObject res; - res["jsonrpc"] = QString::fromStdString("2.0"); - res["method"] = _object["call"]; - res["params"] = _object["args"]; - res["id"] = _object["_id"]; - return QString::fromUtf8(QJsonDocument(res).toJson()); -} - QString QWebThree::callMethod(QString _json) { - QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); - emit processData(formatInput(f), ""); // it's synchronous + emit processData(_json, ""); // it's synchronous return m_response; } diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 10464726e..6028c07cf 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -133,7 +133,7 @@ void ContractDefinition::checkIllegalOverrides() const FunctionDefinition const*& override = functions[name]; if (!override) override = function.get(); - else if (override->isPublic() != function->isPublic() || + else if (override->getVisibility() != function->getVisibility() || override->isDeclaredConst() != function->isDeclaredConst() || FunctionType(*override) != FunctionType(*function)) BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature.")); @@ -475,6 +475,8 @@ void FunctionCall::checkTypeRequirements() // number of non-mapping members if (m_arguments.size() != 1) BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); + if (!m_names.empty()) + BOOST_THROW_EXCEPTION(createTypeError("Type conversion can't allow named arguments.")); if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); m_type = type.getActualType(); @@ -487,9 +489,44 @@ void FunctionCall::checkTypeRequirements() TypePointers const& parameterTypes = functionType->getParameterTypes(); if (parameterTypes.size() != m_arguments.size()) BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); - for (size_t i = 0; i < m_arguments.size(); ++i) - if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) - BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); + + if (m_names.empty()) + { + for (size_t i = 0; i < m_arguments.size(); ++i) + if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); + } + else + { + auto const& parameterNames = functionType->getParameterNames(); + if (parameterNames.size() != m_names.size()) + BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); + + // check duplicate names + for (size_t i = 0; i < m_names.size(); i++) { + for (size_t j = i + 1; j < m_names.size(); j++) { + if (m_names[i] == m_names[j]) + BOOST_THROW_EXCEPTION(createTypeError("Duplicate named argument.")); + } + } + + for (size_t i = 0; i < m_names.size(); i++) { + bool found = false; + for (size_t j = 0; j < parameterNames.size(); j++) { + if (parameterNames[j] == *m_names[i]) { + // check type convertible + if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[j])) + BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); + + found = true; + break; + } + } + if (!found) + BOOST_THROW_EXCEPTION(createTypeError("Named argument doesn't match function declaration.")); + } + } + // @todo actually the return type should be an anonymous struct, // but we change it to the type of the first return value until we have structs if (functionType->getReturnParameterTypes().empty()) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 950553cd4..525907bf4 100755 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -133,12 +133,17 @@ class Declaration: public ASTNode { public: enum class LValueType { NONE, LOCAL, STORAGE }; + enum class Visibility { DEFAULT, PUBLIC, PROTECTED, PRIVATE }; - Declaration(Location const& _location, ASTPointer<ASTString> const& _name): - ASTNode(_location), m_name(_name), m_scope(nullptr) {} + Declaration(Location const& _location, ASTPointer<ASTString> const& _name, + Visibility _visibility = Visibility::DEFAULT): + ASTNode(_location), m_name(_name), m_visibility(_visibility), m_scope(nullptr) {} /// @returns the declared name. ASTString const& getName() const { return *m_name; } + Visibility getVisibility() const { return m_visibility == Visibility::DEFAULT ? getDefaultVisibility() : m_visibility; } + bool isPublic() const { return getVisibility() == Visibility::PUBLIC; } + /// @returns the scope this declaration resides in. Can be nullptr if it is the global scope. /// Available only after name and type resolution step. Declaration const* getScope() const { return m_scope; } @@ -151,8 +156,12 @@ public: /// @returns the lvalue type of expressions referencing this declaration virtual LValueType getLValueType() const { return LValueType::NONE; } +protected: + virtual Visibility getDefaultVisibility() const { return Visibility::PUBLIC; } + private: ASTPointer<ASTString> m_name; + Visibility m_visibility; Declaration const* m_scope; }; @@ -330,16 +339,15 @@ class FunctionDefinition: public Declaration, public VariableScope, public Docum { public: FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name, - bool _isPublic, - bool _isConstructor, + Declaration::Visibility _visibility, bool _isConstructor, ASTPointer<ASTString> const& _documentation, ASTPointer<ParameterList> const& _parameters, bool _isDeclaredConst, std::vector<ASTPointer<ModifierInvocation>> const& _modifiers, ASTPointer<ParameterList> const& _returnParameters, ASTPointer<Block> const& _body): - Declaration(_location, _name), Documented(_documentation), - m_isPublic(_isPublic), m_isConstructor(_isConstructor), + Declaration(_location, _name, _visibility), Documented(_documentation), + m_isConstructor(_isConstructor), m_parameters(_parameters), m_isDeclaredConst(_isDeclaredConst), m_functionModifiers(_modifiers), @@ -350,7 +358,6 @@ public: virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - bool isPublic() const { return m_isPublic; } bool isConstructor() const { return m_isConstructor; } bool isDeclaredConst() const { return m_isDeclaredConst; } std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; } @@ -371,7 +378,6 @@ public: std::string getCanonicalSignature() const; private: - bool m_isPublic; bool m_isConstructor; ASTPointer<ParameterList> m_parameters; bool m_isDeclaredConst; @@ -388,10 +394,10 @@ class VariableDeclaration: public Declaration { public: VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type, - ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false, - bool _isIndexed = false): - Declaration(_location, _name), m_typeName(_type), - m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} + ASTPointer<ASTString> const& _name, Visibility _visibility, + bool _isStateVar = false, bool _isIndexed = false): + Declaration(_location, _name, _visibility), m_typeName(_type), + m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -404,13 +410,14 @@ public: virtual LValueType getLValueType() const override; bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); } - bool isPublic() const { return m_isPublic; } bool isStateVariable() const { return m_isStateVariable; } bool isIndexed() const { return m_isIndexed; } +protected: + Visibility getDefaultVisibility() const override { return Visibility::PROTECTED; } + private: ASTPointer<TypeName> m_typeName; ///< can be empty ("var") - bool m_isPublic; ///< Whether there is an accessor for it or not bool m_isStateVariable; ///< Whether or not this is a contract state variable bool m_isIndexed; ///< Whether this is an indexed variable (used by events). @@ -956,14 +963,15 @@ class FunctionCall: public Expression { public: FunctionCall(Location const& _location, ASTPointer<Expression> const& _expression, - std::vector<ASTPointer<Expression>> const& _arguments): - Expression(_location), m_expression(_expression), m_arguments(_arguments) {} + std::vector<ASTPointer<Expression>> const& _arguments, std::vector<ASTPointer<ASTString>> const& _names): + Expression(_location), m_expression(_expression), m_arguments(_arguments), m_names(_names) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; Expression const& getExpression() const { return *m_expression; } std::vector<ASTPointer<Expression const>> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } + std::vector<ASTPointer<ASTString>> const& getNames() const { return m_names; } /// Returns true if this is not an actual function call, but an explicit type conversion /// or constructor call. @@ -972,6 +980,7 @@ public: private: ASTPointer<Expression> m_expression; std::vector<ASTPointer<Expression>> m_arguments; + std::vector<ASTPointer<ASTString>> m_names; }; /** diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 3c46d4552..389f826b7 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -240,10 +240,6 @@ bool Compiler::visit(VariableDeclaration const& _variableDeclaration) m_context << m_context.getFunctionEntryLabel(_variableDeclaration); ExpressionCompiler::appendStateVariableAccessor(m_context, _variableDeclaration); - unsigned sizeOnStack = _variableDeclaration.getType()->getSizeOnStack(); - solAssert(sizeOnStack <= 15, "Stack too deep."); - m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP; - return false; } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 7d58ea2e2..875e00bc2 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -22,6 +22,7 @@ #include <utility> #include <numeric> +#include <boost/range/adaptor/reversed.hpp> #include <libdevcore/Common.h> #include <libdevcrypto/SHA3.h> #include <libsolidity/AST.h> @@ -194,6 +195,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { //@todo struct construction solAssert(_functionCall.getArguments().size() == 1, ""); + solAssert(_functionCall.getNames().empty(), ""); Expression const& firstArgument = *_functionCall.getArguments().front(); firstArgument.accept(*this); appendTypeConversion(*firstArgument.getType(), *_functionCall.getType()); @@ -201,8 +203,26 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType()); - vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments(); - solAssert(arguments.size() == function.getParameterTypes().size(), ""); + TypePointers const& parameterTypes = function.getParameterTypes(); + vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments(); + vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames(); + solAssert(callArguments.size() == parameterTypes.size(), ""); + + vector<ASTPointer<Expression const>> arguments; + if (callArgumentNames.empty()) + // normal arguments + arguments = callArguments; + else + // named arguments + for (auto const& parameterName: function.getParameterNames()) + { + bool found = false; + for (size_t j = 0; j < callArgumentNames.size() && !found; j++) + if ((found = (parameterName == *callArgumentNames[j]))) + // we found the actual parameter position + arguments.push_back(callArguments[j]); + solAssert(found, ""); + } switch (function.getLocation()) { @@ -823,26 +843,58 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ return length; } -unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, - Expression const& _expression, unsigned _memoryOffset) +unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, + Location const& _location, unsigned _memoryOffset) { - _expression.accept(*this); - appendTypeConversion(*_expression.getType(), _expectedType, true); + appendTypeConversion(_type, _expectedType, true); unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); if (c_numBytes == 0 || c_numBytes > 32) BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_sourceLocation(_location) << errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; bool const c_padToWords = true; return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); } +unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, + Expression const& _expression, + unsigned _memoryOffset) +{ + _expression.accept(*this); + return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset); +} + void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) { - m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); - solAssert(m_currentLValue.isInStorage(), ""); - m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true); + FunctionType thisType(_varDecl); + solAssert(thisType.getReturnParameterTypes().size() == 1, ""); + TypePointer const& resultType = thisType.getReturnParameterTypes().front(); + unsigned sizeOnStack; + + unsigned length = 0; + TypePointers const& params = thisType.getParameterTypes(); + // move arguments to memory + for (TypePointer const& param: boost::adaptors::reverse(params)) + length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length); + + // retrieve the position of the mapping + m_context << m_context.getStorageLocationOfVariable(_varDecl); + + for (TypePointer const& param: params) + { + // move offset to memory + CompilerUtils(m_context).storeInMemory(length); + unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize()); + length -= argLen; + m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; + } + + m_currentLValue = LValue(m_context, LValue::STORAGE, *resultType); + m_currentLValue.retrieveValue(resultType, Location(), true); + sizeOnStack = resultType->getSizeOnStack(); + solAssert(sizeOnStack <= 15, "Stack too deep."); + m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP; } ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index caecbfe8d..7de577e6c 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -97,6 +97,10 @@ private: unsigned appendArgumentCopyToMemory(TypePointers const& _types, std::vector<ASTPointer<Expression const>> const& _arguments, unsigned _memoryOffset = 0); + /// Appends code that copies a type to memory. + /// @returns the number of bytes copied to memory + unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, + Location const& _location, unsigned _memoryOffset = 0); /// Appends code that evaluates a single expression and copies it to memory (with optional offset). /// @returns the number of bytes copied to memory unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index d2e888a8d..0ad7bd7ca 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -131,27 +131,19 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() } while (m_scanner->getCurrentToken() == Token::COMMA); expectToken(Token::LBRACE); - bool visibilityIsPublic = true; while (true) { Token::Value currentToken = m_scanner->getCurrentToken(); if (currentToken == Token::RBRACE) break; - else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE) - { - visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC); - m_scanner->next(); - expectToken(Token::COLON); - } else if (currentToken == Token::FUNCTION) - functions.push_back(parseFunctionDefinition(visibilityIsPublic, name.get())); + functions.push_back(parseFunctionDefinition(name.get())); else if (currentToken == Token::STRUCT) structs.push_back(parseStructDefinition()); else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING || Token::isElementaryTypeName(currentToken)) { VarDeclParserOptions options; - options.isPublic = visibilityIsPublic; options.isStateVariable = true; stateVariables.push_back(parseVariableDeclaration(options)); expectToken(Token::SEMICOLON); @@ -177,7 +169,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() if (m_scanner->getCurrentToken() == Token::LPAREN) { m_scanner->next(); - arguments = parseFunctionCallArguments(); + arguments = parseFunctionCallListArguments(); nodeFactory.markEndPosition(); expectToken(Token::RPAREN); } @@ -186,7 +178,22 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() return nodeFactory.createNode<InheritanceSpecifier>(name, arguments); } -ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, ASTString const* _contractName) +Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) +{ + Declaration::Visibility visibility; + if (_token == Token::PUBLIC) + visibility = Declaration::Visibility::PUBLIC; + else if (_token == Token::PROTECTED) + visibility = Declaration::Visibility::PROTECTED; + else if (_token == Token::PRIVATE) + visibility = Declaration::Visibility::PRIVATE; + else + solAssert(false, "Invalid visibility specifier."); + m_scanner->next(); + return visibility; +} + +ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName) { ASTNodeFactory nodeFactory(*this); ASTPointer<ASTString> docstring; @@ -201,16 +208,24 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A name = expectIdentifierToken(); ASTPointer<ParameterList> parameters(parseParameterList()); bool isDeclaredConst = false; + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); vector<ASTPointer<ModifierInvocation>> modifiers; while (true) { - if (m_scanner->getCurrentToken() == Token::CONST) + Token::Value token = m_scanner->getCurrentToken(); + if (token == Token::CONST) { isDeclaredConst = true; m_scanner->next(); } - else if (m_scanner->getCurrentToken() == Token::IDENTIFIER) + else if (token == Token::IDENTIFIER) modifiers.push_back(parseModifierInvocation()); + else if (Token::isVisibilitySpecifier(token)) + { + if (visibility != Declaration::Visibility::DEFAULT) + BOOST_THROW_EXCEPTION(createParserError("Multiple visibility specifiers.")); + visibility = parseVisibilitySpecifier(token); + } else break; } @@ -226,7 +241,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A ASTPointer<Block> block = parseBlock(); nodeFactory.setEndPositionFromNode(block); bool const c_isConstructor = (_contractName && *name == *_contractName); - return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, c_isConstructor, docstring, + return nodeFactory.createNode<FunctionDefinition>(name, visibility, c_isConstructor, docstring, parameters, isDeclaredConst, modifiers, returnParameters, block); } @@ -253,14 +268,18 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOp ASTNodeFactory nodeFactory(*this); ASTPointer<TypeName> type = parseTypeName(_options.allowVar); bool isIndexed = false; - if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED) + Token::Value token = m_scanner->getCurrentToken(); + if (_options.allowIndexed && token == Token::INDEXED) { isIndexed = true; m_scanner->next(); } + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); + if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) + visibility = parseVisibilitySpecifier(token); nodeFactory.markEndPosition(); return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), - _options.isPublic, _options.isStateVariable, + visibility, _options.isStateVariable, isIndexed); } @@ -313,7 +332,7 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() if (m_scanner->getCurrentToken() == Token::LPAREN) { m_scanner->next(); - arguments = parseFunctionCallArguments(); + arguments = parseFunctionCallListArguments(); nodeFactory.markEndPosition(); expectToken(Token::RPAREN); } @@ -573,7 +592,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence) ASTPointer<Expression> expression = parseUnaryExpression(); int precedence = Token::precedence(m_scanner->getCurrentToken()); for (; precedence >= _minPrecedence; --precedence) - { while (Token::precedence(m_scanner->getCurrentToken()) == precedence) { Token::Value op = m_scanner->getCurrentToken(); @@ -582,7 +600,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence) nodeFactory.setEndPositionFromNode(right); expression = nodeFactory.createNode<BinaryOperation>(expression, op, right); } - } return expression; } @@ -648,10 +665,12 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression() case Token::LPAREN: { m_scanner->next(); - vector<ASTPointer<Expression>> arguments = parseFunctionCallArguments(); + vector<ASTPointer<Expression>> arguments; + vector<ASTPointer<ASTString>> names; + std::tie(arguments, names) = parseFunctionCallArguments(); nodeFactory.markEndPosition(); expectToken(Token::RPAREN); - expression = nodeFactory.createNode<FunctionCall>(expression, arguments); + expression = nodeFactory.createNode<FunctionCall>(expression, arguments, names); } break; default: @@ -704,7 +723,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() return expression; } -vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments() +vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments() { vector<ASTPointer<Expression>> arguments; if (m_scanner->getCurrentToken() != Token::RPAREN) @@ -719,6 +738,32 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments() return arguments; } +pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseFunctionCallArguments() +{ + pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret; + Token::Value token = m_scanner->getCurrentToken(); + if (token == Token::LBRACE) + { + // call({arg1 : 1, arg2 : 2 }) + expectToken(Token::LBRACE); + while (m_scanner->getCurrentToken() != Token::RBRACE) + { + ret.second.push_back(expectIdentifierToken()); + expectToken(Token::COLON); + ret.first.push_back(parseExpression()); + + if (m_scanner->getCurrentToken() == Token::COMMA) + expectToken(Token::COMMA); + else + break; + } + expectToken(Token::RBRACE); + } + else + ret.first = parseFunctionCallListArguments(); + return ret; +} + bool Parser::peekVariableDefinition() { diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 413a2711e..19e0af1aa 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -48,7 +48,6 @@ private: struct VarDeclParserOptions { VarDeclParserOptions() {} bool allowVar = false; - bool isPublic = false; bool isStateVariable = false; bool allowIndexed = false; }; @@ -58,7 +57,8 @@ private: ASTPointer<ImportDirective> parseImportDirective(); ASTPointer<ContractDefinition> parseContractDefinition(); ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier(); - ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName); + Declaration::Visibility parseVisibilitySpecifier(Token::Value _token); + ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName); ASTPointer<StructDefinition> parseStructDefinition(); ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); ASTPointer<ModifierDefinition> parseModifierDefinition(); @@ -81,7 +81,8 @@ private: ASTPointer<Expression> parseUnaryExpression(); ASTPointer<Expression> parseLeftHandSideExpression(); ASTPointer<Expression> parsePrimaryExpression(); - std::vector<ASTPointer<Expression>> parseFunctionCallArguments(); + std::vector<ASTPointer<Expression>> parseFunctionCallListArguments(); + std::pair<std::vector<ASTPointer<Expression>>, std::vector<ASTPointer<ASTString>>> parseFunctionCallArguments(); ///@} ///@{ diff --git a/libsolidity/Token.h b/libsolidity/Token.h index ed42f90cc..76e504499 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -165,6 +165,7 @@ namespace solidity K(NEW, "new", 0) \ K(PUBLIC, "public", 0) \ K(PRIVATE, "private", 0) \ + K(PROTECTED, "protected", 0) \ K(RETURN, "return", 0) \ K(RETURNS, "returns", 0) \ K(STRUCT, "struct", 0) \ @@ -376,6 +377,7 @@ public: static bool isUnaryOp(Value op) { return (NOT <= op && op <= DELETE) || op == ADD || op == SUB; } static bool isCountOp(Value op) { return op == INC || op == DEC; } static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); } + static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; } // Returns a string corresponding to the JS token string // (.e., "<" for the token LT) or NULL if the token doesn't diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index ab401332a..54e701c10 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -621,11 +621,24 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal FunctionType::FunctionType(VariableDeclaration const& _varDecl): m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl) { - TypePointers params({}); - vector<string> paramNames({}); - TypePointers retParams({_varDecl.getType()}); - vector<string> retParamNames({ _varDecl.getName()}); - // for now, no input parameters LTODO: change for some things like mapping + TypePointers params; + vector<string> paramNames; + TypePointers retParams; + vector<string> retParamNames; + TypePointer varDeclType = _varDecl.getType(); + auto mappingType = dynamic_cast<MappingType const*>(varDeclType.get()); + auto returnType = varDeclType; + + while (mappingType != nullptr) + { + params.push_back(mappingType->getKeyType()); + paramNames.push_back(""); + returnType = mappingType->getValueType(); + mappingType = dynamic_cast<MappingType const*>(mappingType->getValueType().get()); + } + + retParams.push_back(returnType); + retParamNames.push_back(""); swap(params, m_parameterTypes); swap(paramNames, m_parameterNames); diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index b97dac5db..1785b516c 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -1,14 +1,15 @@ ContractDefinition = 'contract' Identifier ( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )? '{' ContractPart* '}' -ContractPart = VariableDeclaration ';' | StructDefinition | ModifierDefinition | - FunctionDefinition | 'public:' | 'private:' +ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )? StructDefinition = 'struct' Identifier '{' ( VariableDeclaration (';' VariableDeclaration)* )? '} +StateVariableDeclaration = TypeName ( 'public' | 'protected' | 'private' )? Identifier ';' ModifierDefinition = 'modifier' Identifier ParameterList? Block -FunctionDefinition = 'function' Identifier ParameterList ( Identifier | 'constant' )* +FunctionDefinition = 'function' Identifier ParameterList + ( Identifier | 'constant' | 'public' | 'protected' | 'private' )* ( 'returns' ParameterList )? Block ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')' // semantic restriction: mappings and structs (recursively) containing mappings diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index ad9c78e9b..e27eac9fd 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -63,6 +63,12 @@ void AppContext::load() m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); + qmlRegisterType<QIntType>("org.ethereum.qml.QIntType", 1, 0, "QIntType"); + qmlRegisterType<QRealType>("org.ethereum.qml.QRealType", 1, 0, "QRealType"); + qmlRegisterType<QStringType>("org.ethereum.qml.QStringType", 1, 0, "QStringType"); + qmlRegisterType<QHashType>("org.ethereum.qml.QHashType", 1, 0, "QHashType"); + qmlRegisterType<QBoolType>("org.ethereum.qml.QBoolType", 1, 0, "QBoolType"); + qmlRegisterType<QVariableDeclaration>("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 7fe514c09..365dce9a9 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -66,6 +66,10 @@ ClientModel::ClientModel(AppContext* _context): m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()), m_contractAddress(Address()) { qRegisterMetaType<QBigInt*>("QBigInt*"); + qRegisterMetaType<QIntType*>("QIntType*"); + qRegisterMetaType<QStringType*>("QStringType*"); + qRegisterMetaType<QRealType*>("QRealType*"); + qRegisterMetaType<QHashType*>("QHashType*"); qRegisterMetaType<QEther*>("QEther*"); qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*"); qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*"); @@ -146,13 +150,13 @@ void ClientModel::setupState(QVariantMap _state) } else { - QVariantMap params = transaction.value("parameters").toMap(); + QVariantList qParams = transaction.value("qType").toList(); TransactionSettings transactionSettings(functionId, value, gas, gasPrice); - for (auto p = params.cbegin(); p != params.cend(); ++p) + for (QVariant const& variant: qParams) { - QBigInt* param = qvariant_cast<QBigInt*>(p.value()); - transactionSettings.parameterValues.insert(std::make_pair(p.key(), boost::get<dev::u256>(param->internalValue()))); + QVariableDefinition* param = qvariant_cast<QVariableDefinition*>(variant); + transactionSettings.parameterValues.push_back(param); } if (transaction.value("executeConstructor").toBool()) @@ -212,14 +216,11 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); encoder.encode(f); - for (int p = 0; p < f->parametersList().size(); p++) + for (int p = 0; p < transaction.parameterValues.size(); p++) { - QVariableDeclaration* var = f->parametersList().at(p); - u256 value = 0; - auto v = transaction.parameterValues.find(var->name()); - if (v != transaction.parameterValues.cend()) - value = v->second; - encoder.encode(var, value); + if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) + BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(f->parametersList().at(p)->type().toStdString())); + encoder.push(transaction.parameterValues.at(p)->encodeValue()); } if (transaction.functionId.isEmpty()) @@ -330,11 +331,6 @@ void ClientModel::onNewTransaction() bool creation = tr.contractAddress != 0; - if (creation) - returned = QString::fromStdString(toJS(tr.contractAddress)); - else - returned = QString::fromStdString(toJS(tr.returnValue)); - //TODO: handle value transfer FixedHash<4> functionHash; bool call = false; @@ -363,6 +359,9 @@ void ClientModel::onNewTransaction() function = QObject::tr("<none>"); } + if (creation) + returned = QString::fromStdString(toJS(tr.contractAddress)); + if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress)) { auto compilerRes = m_context->codeModel()->code(); @@ -372,7 +371,13 @@ void ClientModel::onNewTransaction() { QFunctionDefinition* funcDef = def->getFunction(functionHash); if (funcDef) + { function = funcDef->name(); + ContractCallDataEncoder encoder; + QList<QVariableDefinition*> returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); + for (auto const& var: returnValues) + returned += var->value() + " | "; + } } } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 37fbfbbc5..493290780 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -39,6 +39,7 @@ class RpcConnector; class QEther; class QDebugData; class MixClient; +class QVariableDefinition; /// Backend transaction config class struct TransactionSettings @@ -60,7 +61,7 @@ struct TransactionSettings /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value - std::map<QString, u256> parameterValues; + QList<QVariableDefinition*> parameterValues; /// Standard contract url QString stdContractUrl; }; diff --git a/mix/CodeHighlighter.cpp b/mix/CodeHighlighter.cpp index 49d01b418..c1ef39d5d 100644 --- a/mix/CodeHighlighter.cpp +++ b/mix/CodeHighlighter.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of cpp-ethereum. - cpp-ethereum 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. + cpp-ethereum 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. - cpp-ethereum 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. + cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. */ /** @file CodeHighlighter.cpp * @author Arkadiy Paronyan arkadiy@ethdev.com diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 7a38db22b..bdec95ca4 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -44,89 +44,37 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function) m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end()); } -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, bool _value) +void ContractCallDataEncoder::push(bytes const& _b) { - return encode(_dec, QString(formatBool(_value))); + m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end()); } -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, QString _value) -{ - int padding = this->padding(_dec->type()); - bytes data = padded(jsToBytes(_value.toStdString()), padding); - m_encodedData.insert(m_encodedData.end(), data.begin(), data.end()); -} - -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, u256 _value) -{ - int padding = this->padding(_dec->type()); - std::ostringstream s; - s << std::hex << "0x" << _value; - bytes data = padded(jsToBytes(s.str()), padding); - m_encodedData.insert(m_encodedData.end(), data.begin(), data.end()); - encodedData(); -} - -QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> _returnParameters, bytes _value) +QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const& _returnParameters, bytes _value) { QList<QVariableDefinition*> r; - std::string returnValue = toJS(_value); - returnValue = returnValue.substr(2, returnValue.length() - 1); for (int k = 0; k <_returnParameters.length(); k++) { QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k); - int padding = this->padding(dec->type()); - std::string rawParam = returnValue.substr(0, padding * 2); - r.append(new QVariableDefinition(dec, convertToReadable(unpadLeft(rawParam), dec))); - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + QVariableDefinition* def = nullptr; + if (dec->type().contains("int")) + def = new QIntType(dec, QString()); + else if (dec->type().contains("real")) + def = new QRealType(dec, QString()); + else if (dec->type().contains("bool")) + def = new QBoolType(dec, QString()); + else if (dec->type().contains("string") || dec->type().contains("text")) + def = new QStringType(dec, QString()); + else if (dec->type().contains("hash") || dec->type().contains("address")) + def = new QHashType(dec, QString()); + else + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found")); + + bytes rawParam(_value.begin(), _value.begin() + 32); + def->decodeValue(rawParam); + r.push_back(def); + if (_value.size() > 32) + _value = bytes(_value.begin() + 32, _value.end()); + qDebug() << "decoded return value : " << dec->type() << " " << def->value(); } return r; } - -int ContractCallDataEncoder::padding(QString type) -{ - // TODO : to be improved (load types automatically from solidity library). - if (type.indexOf("uint") != -1) - return integerPadding(type.remove("uint").toInt()); - else if (type.indexOf("int") != -1) - return integerPadding(type.remove("int").toInt()); - else if (type.indexOf("bool") != -1) - return 1; - else if ((type.indexOf("address") != -1)) - return 32; - else - return 0; -} - -int ContractCallDataEncoder::integerPadding(int bitValue) -{ - return bitValue / 8; -} - -QString ContractCallDataEncoder::formatBool(bool _value) -{ - return (_value ? "1" : "0"); -} - -QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec) -{ - if (_dec->type().indexOf("int") != -1) - return convertToInt(_v); - else if (_dec->type().indexOf("bool") != -1) - return convertToBool(_v); - else - return QString::fromStdString(_v); -} - -QString ContractCallDataEncoder::convertToBool(std::string _v) -{ - return _v == "1" ? "true" : "false"; -} - -QString ContractCallDataEncoder::convertToInt(std::string _v) -{ - //TO DO to be improve to manage all int, uint size (128, 256, ...) in ethereum QML types task #612. - int x = std::stol(_v, nullptr, 16); - std::stringstream ss; - ss << std::dec << x; - return QString::fromStdString(ss.str()); -} diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index 49410a7cd..718beb8e0 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -41,27 +41,17 @@ class ContractCallDataEncoder { public: ContractCallDataEncoder() {} - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, QString _value); - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, u256 _value); - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, bool _value); /// Encode hash of the function to call. void encode(QFunctionDefinition const* _function); /// Decode variable in order to be sent to QML view. - QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> _dec, bytes _value); + QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> const& _dec, bytes _value); /// Get all encoded data encoded by encode function. bytes encodedData(); + /// Push the given @a _b to the current param context. + void push(bytes const& _b); private: - int padding(QString _type); bytes m_encodedData; - static QString convertToReadable(std::string _v, QVariableDeclaration* _dec); - static QString convertToBool(std::string _v); - static QString convertToInt(std::string _v); - static int integerPadding(int _bitValue); - static QString formatBool(bool _value); }; } diff --git a/mix/Exceptions.h b/mix/Exceptions.h index ea4cb87b3..5403879f1 100644 --- a/mix/Exceptions.h +++ b/mix/Exceptions.h @@ -38,6 +38,7 @@ struct FileIoException: virtual Exception {}; struct InvalidBlockException: virtual Exception {}; struct FunctionNotFoundException: virtual Exception {}; struct ExecutionStateException: virtual Exception {}; +struct ParameterChangedException: virtual Exception {}; typedef boost::error_info<struct tagQmlError, QQmlError> QmlErrorInfo; typedef boost::error_info<struct tagFileError, std::string> FileError; diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 293d4036e..a6c833532 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -56,16 +56,15 @@ void MixClient::resetState(u256 _balance) genesis.state = m_state; Block open; m_blocks = Blocks { genesis, open }; //last block contains a list of pending transactions to be finalized - m_lastHashes.clear(); - m_lastHashes.resize(256); - m_lastHashes[0] = genesis.hash; +// m_lastHashes.clear(); +// m_lastHashes.resize(256); +// m_lastHashes[0] = genesis.hash; } void MixClient::executeTransaction(Transaction const& _t, State& _state) { bytes rlp = _t.rlp(); - - Executive execution(_state, m_lastHashes, 0); + Executive execution(_state, LastHashes(), 0); execution.setup(&rlp); std::vector<MachineState> machineStates; std::vector<unsigned> levels; @@ -165,14 +164,12 @@ void MixClient::mine() Block& block = m_blocks.back(); m_state.mine(0, true); m_state.completeMine(); - m_state.commitToMine(); + m_state.commitToMine(BlockChain()); + m_state.cleanup(true); block.state = m_state; block.info = m_state.info(); block.hash = block.info.hash; - m_state.cleanup(true); m_blocks.push_back(Block()); - m_lastHashes.insert(m_lastHashes.begin(), block.hash); - m_lastHashes.resize(256); h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; noteChanged(changed); diff --git a/mix/MixClient.h b/mix/MixClient.h index 6118613ed..c34fff60b 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -106,7 +106,6 @@ private: std::map<h256, dev::eth::InstalledFilter> m_filters; std::map<unsigned, dev::eth::ClientWatch> m_watches; Blocks m_blocks; - eth::LastHashes m_lastHashes; }; } diff --git a/mix/QBigInt.h b/mix/QBigInt.h index 842b86c7d..c6ec72305 100644 --- a/mix/QBigInt.h +++ b/mix/QBigInt.h @@ -36,7 +36,7 @@ namespace dev namespace mix { -using BigIntVariant = boost::variant<dev::u256, dev::bigint>; +using BigIntVariant = boost::variant<dev::u256, dev::bigint, dev::s256>; struct add: public boost::static_visitor<BigIntVariant> { @@ -75,6 +75,7 @@ public: QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){ QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } + QBigInt(dev::s256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } ~QBigInt() {} /// @returns the current used big integer. diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index f9cc5265f..fcd83cb30 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -19,6 +19,8 @@ * @date 2014 */ +#include <QDebug> +#include <QStringList> #include <libsolidity/AST.h> #include "QBasicNodeDefinition.h" @@ -32,16 +34,20 @@ namespace mix class QVariableDeclaration: public QBasicNodeDefinition { Q_OBJECT - Q_PROPERTY(QString type READ type CONSTANT) + Q_PROPERTY(QString type READ type WRITE setType) public: QVariableDeclaration() {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} QVariableDeclaration(std::string const& _name, std::string const& _type): QBasicNodeDefinition(_name), m_type(QString::fromStdString(_type)) {} QString type() const { return m_type; } + void setType(QString _type) { m_type = _type; } + private: QString m_type; }; } } + +Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*) diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index 4f38e84b2..a76388d68 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -19,6 +19,8 @@ * @date 2014 */ +#include <libdevcore/CommonData.h> +#include <libdevcore/CommonJS.h> #include "QVariableDefinition.h" using namespace dev::mix; @@ -53,3 +55,91 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx) return nullptr; return m_def.at(_idx); } + +/* + * QIntType + */ +void QIntType::setValue(dev::bigint _value) +{ + m_bigIntvalue = _value; + std::stringstream str; + str << std::dec << m_bigIntvalue; + m_value = QString::fromStdString(str.str()); +} + +dev::bytes QIntType::encodeValue() +{ + dev::bigint i(value().toStdString()); + bytes ret(32); + toBigEndian((u256)i, ret); + return ret; +} + +void QIntType::decodeValue(dev::bytes const& _rawValue) +{ + dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue); + if (un >> 255) + setValue(-s256(~un + 1)); + else + setValue(un); +} + +/* + * QHashType + */ +dev::bytes QHashType::encodeValue() +{ + QByteArray bytesAr = value().toLocal8Bit(); + bytes r = bytes(bytesAr.begin(), bytesAr.end()); + return padded(r, 32); +} + +void QHashType::decodeValue(dev::bytes const& _rawValue) +{ + std::string _ret = asString(unpadLeft(_rawValue)); + setValue(QString::fromStdString(_ret)); +} + +/* + * QRealType + */ +dev::bytes QRealType::encodeValue() +{ + return bytes(); +} + +void QRealType::decodeValue(dev::bytes const& _rawValue) +{ + Q_UNUSED(_rawValue); +} + +/* + * QStringType + */ +dev::bytes QStringType::encodeValue() +{ + QByteArray b = value().toUtf8(); + bytes r = bytes(b.begin(), b.end()); + return paddedRight(r, 32); +} + +void QStringType::decodeValue(dev::bytes const& _rawValue) +{ + setValue(QString::fromUtf8((char*)_rawValue.data())); +} + +/* + * QBoolType + */ +dev::bytes QBoolType::encodeValue() +{ + return padded(jsToBytes(value().toStdString()), 32); +} + +void QBoolType::decodeValue(dev::bytes const& _rawValue) +{ + byte ret = _rawValue.at(_rawValue.size() - 1); + bool boolRet = (ret == byte(1)); + m_boolValue = boolRet; + m_value = m_boolValue ? "1" : "0"; +} diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index f55e51346..ae9bf9459 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -22,6 +22,7 @@ #pragma once #include <QAbstractListModel> +#include "QBigInt.h" #include "QVariableDeclaration.h" namespace dev @@ -37,15 +38,26 @@ class QVariableDefinition: public QObject Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT) public: + QVariableDefinition() {} QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {} - /// Return the associated declaration of this variable definition. - QVariableDeclaration* declaration() const { return m_dec; } + /// Return the associated declaration of this variable definition. Invokable from QML. + Q_INVOKABLE QVariableDeclaration* declaration() const { return m_dec; } /// Return the variable value. QString value() const { return m_value; } + /// Set a new value for this instance. Invokable from QML. + Q_INVOKABLE void setValue(QString _value) { m_value = _value; } + /// Set a new Declaration for this instance. Invokable from QML. + Q_INVOKABLE void setDeclaration(QVariableDeclaration* _dec) { m_dec = _dec; } + /// Encode the current value in order to be used as function parameter. + virtual bytes encodeValue() = 0; + /// Decode the return value @a _rawValue. + virtual void decodeValue(dev::bytes const& _rawValue) = 0; + +protected: + QString m_value; private: - QString m_value; QVariableDeclaration* m_dec; }; @@ -67,7 +79,77 @@ private: QList<QVariableDefinition*> m_def; }; +class QIntType: public QVariableDefinition +{ + Q_OBJECT + +public: + QIntType() {} + QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(dev::bytes const& _rawValue) override; + /// @returns an instance of QBigInt for the current value. + QBigInt* toBigInt() { return new QBigInt(m_bigIntvalue); } + dev::bigint bigInt() { return m_bigIntvalue; } + void setValue(dev::bigint _value); + +private: + dev::bigint m_bigIntvalue; +}; + +class QRealType: public QVariableDefinition +{ + Q_OBJECT + +public: + QRealType() {} + QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(dev::bytes const& _rawValue) override; +}; + +class QStringType: public QVariableDefinition +{ + Q_OBJECT + +public: + QStringType() {} + QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(dev::bytes const& _rawValue) override; +}; + +class QHashType: public QVariableDefinition +{ + Q_OBJECT + +public: + QHashType() {} + QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(dev::bytes const& _rawValue) override; +}; + +class QBoolType: public QVariableDefinition +{ + Q_OBJECT + +public: + QBoolType() {} + QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(dev::bytes const& _rawValue) override; + /// @returns the boolean value for the current definition. + bool toBool() { return m_boolValue; } + +private: + bool m_boolValue; +}; + } } -Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*) +Q_DECLARE_METATYPE(dev::mix::QIntType*) +Q_DECLARE_METATYPE(dev::mix::QStringType*) +Q_DECLARE_METATYPE(dev::mix::QHashType*) +Q_DECLARE_METATYPE(dev::mix::QBoolType*) diff --git a/mix/qml/QBoolType.qml b/mix/qml/QBoolType.qml new file mode 100644 index 000000000..9f5fe6fd7 --- /dev/null +++ b/mix/qml/QBoolType.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QBoolType 1.0 + +QBoolType +{ +} + diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml new file mode 100644 index 000000000..a52601bdb --- /dev/null +++ b/mix/qml/QBoolTypeView.qml @@ -0,0 +1,42 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.3 + +Item +{ + id: editRoot + property string text + property string defaultValue + + Rectangle { + anchors.fill: parent + ComboBox + { + property bool inited: false + Component.onCompleted: + { + if (text === "") + currentIndex = parseInt(defaultValue); + else + currentIndex = parseInt(text); + inited = true + } + + id: boolCombo + anchors.fill: parent + onCurrentIndexChanged: + { + if (inited) + text = comboModel.get(currentIndex).value; + } + model: ListModel + { + id: comboModel + ListElement { text: qsTr("False"); value: "0" } + ListElement { text: qsTr("True"); value: "1" } + } + } + } +} + + + diff --git a/mix/qml/QHashType.qml b/mix/qml/QHashType.qml new file mode 100644 index 000000000..cbd2618cf --- /dev/null +++ b/mix/qml/QHashType.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QHashType 1.0 + +QHashType +{ +} + diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml new file mode 100644 index 000000000..e36514fab --- /dev/null +++ b/mix/qml/QHashTypeView.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + wrapMode: Text.WrapAnywhere + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} diff --git a/mix/qml/QIntType.qml b/mix/qml/QIntType.qml new file mode 100644 index 000000000..241bd4a12 --- /dev/null +++ b/mix/qml/QIntType.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QIntType 1.0 + +QIntType +{ +} + diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml new file mode 100644 index 000000000..f794a3b2d --- /dev/null +++ b/mix/qml/QIntTypeView.qml @@ -0,0 +1,24 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} + + + diff --git a/mix/qml/QRealType.qml b/mix/qml/QRealType.qml new file mode 100644 index 000000000..9a015b1c7 --- /dev/null +++ b/mix/qml/QRealType.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QRealType 1.0 + +QRealType +{ +} + diff --git a/mix/qml/QRealTypeView.qml b/mix/qml/QRealTypeView.qml new file mode 100644 index 000000000..96db4de75 --- /dev/null +++ b/mix/qml/QRealTypeView.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Component +{ + Rectangle { + anchors.fill: parent + Text{ + anchors.fill: parent + text: qsTr("Real") + } + } +} + + + diff --git a/mix/qml/QStringType.qml b/mix/qml/QStringType.qml new file mode 100644 index 000000000..4113fec20 --- /dev/null +++ b/mix/qml/QStringType.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QStringType 1.0 + +QStringType +{ +} + diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml new file mode 100644 index 000000000..a78fc1d26 --- /dev/null +++ b/mix/qml/QStringTypeView.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + wrapMode: Text.WrapAnywhere + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} + + + diff --git a/mix/qml/QVariableDeclaration.qml b/mix/qml/QVariableDeclaration.qml new file mode 100644 index 000000000..dc21d40a7 --- /dev/null +++ b/mix/qml/QVariableDeclaration.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QVariableDeclaration 1.0 + +QVariableDeclaration +{ +} + diff --git a/mix/qml/QVariableDefinition.qml b/mix/qml/QVariableDefinition.qml new file mode 100644 index 000000000..af0cd4ea0 --- /dev/null +++ b/mix/qml/QVariableDefinition.qml @@ -0,0 +1,13 @@ +/* + * Used to instanciate a QVariableDefinition obj using Qt.createComponent function. +*/ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.1 +import org.ethereum.qml.QVariableDefinition 1.0 + +QVariableDefinition +{ + id: qVariableDefinition +} diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index c00e3226f..fa48c640e 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -33,9 +33,10 @@ Window { transactionsModel.append(item.transactions[t]); stateTransactions.push(item.transactions[t]); } - isDefault = setDefault; visible = true; + isDefault = setDefault; titleField.focus = true; + defaultCheckBox.enabled = !isDefault; } function close() { @@ -167,6 +168,7 @@ Window { onClicked: transactionsModel.editTransaction(index) } ToolButton { + visible: index >= 0 ? !transactionsModel.get(index).executeConstructor : false text: qsTr("Delete"); Layout.fillHeight: true onClicked: transactionsModel.deleteTransaction(index) diff --git a/mix/qml/StateList.qml b/mix/qml/StateList.qml index ad14cf30e..3674e0dbc 100644 --- a/mix/qml/StateList.qml +++ b/mix/qml/StateList.qml @@ -48,6 +48,7 @@ Rectangle { onClicked: list.model.editState(index); } ToolButton { + visible: list.model.count - 1 != index text: qsTr("Delete"); Layout.fillHeight: true onClicked: list.model.deleteState(index); diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 6f8fd3a1a..a1b24fe0f 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -8,7 +8,7 @@ import "js/QEtherHelper.js" as QEtherHelper Item { - property int defaultStateIndex: -1 + property int defaultStateIndex: 0 property alias model: stateListModel property var stateList: [] @@ -31,12 +31,30 @@ Item { stdContract: t.stdContract, parameters: {} }; - for (var key in t.parameters) { - var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); - var param = intComponent.createObject(); - param.setValue(t.parameters[key]); - r.parameters[key] = param; + var qType = []; + for (var key in t.parameters) + { + r.parameters[key] = t.parameters[key].value; + var type = t.parameters[key].type; + var varComponent; + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + + var param = varComponent.createObject(stateListModel); + var dec = Qt.createComponent("qrc:/qml/QVariableDeclaration.qml"); + param.setDeclaration(dec.createObject(stateListModel, { "type": type })); + param.setValue(r.parameters[key]); + qType.push(param); } + r.qType = qType; return r; } @@ -48,6 +66,16 @@ Item { }; } + function getParamType(param, params) + { + for (var k in params) + { + if (params[k].declaration.name === param) + return params[k].declaration.type; + } + return ''; + } + function toPlainTransactionItem(t) { var r = { functionId: t.functionId, @@ -60,7 +88,14 @@ Item { parameters: {} }; for (var key in t.parameters) - r.parameters[key] = t.parameters[key].value(); + { + var param = { + name: key, + value: t.parameters[key], + type: getParamType(key, t.qType) + } + r.parameters[key] = param; + } return r; } @@ -70,20 +105,7 @@ Item { stateListModel.clear(); stateList = []; } - onProjectLoading: { - if (!projectData.states) - projectData.states = []; - if (projectData.defaultStateIndex !== undefined) - defaultStateIndex = projectData.defaultStateIndex; - else - defaultStateIndex = -1; - var items = projectData.states; - for(var i = 0; i < items.length; i++) { - var item = fromPlainStateItem(items[i]); - stateListModel.append(item); - stateList.push(item); - } - } + onProjectLoading: stateListModel.loadStatesFromProject(projectData); onProjectSaving: { projectData.states = [] for(var i = 0; i < stateListModel.count; i++) { @@ -114,7 +136,8 @@ Item { stateList.push(item); stateListModel.append(item); } - + if (stateDialog.isDefault) + stateListModel.defaultStateChanged(); stateListModel.save(); } } @@ -126,6 +149,9 @@ Item { ListModel { id: stateListModel + signal defaultStateChanged; + signal stateListModelReady; + function defaultTransactionItem() { return { value: QEtherHelper.createEther("100", QEther.Wei), @@ -164,7 +190,7 @@ Item { function addState() { var item = createDefaultState(); - stateDialog.open(stateListModel.count, item, defaultStateIndex === -1); + stateDialog.open(stateListModel.count, item, false); } function editState(index) { @@ -185,12 +211,37 @@ Item { stateListModel.remove(index); stateList.splice(index, 1); if (index === defaultStateIndex) - defaultStateIndex = -1; + { + defaultStateIndex = 0; + defaultStateChanged(); + } save(); } function save() { projectModel.saveProject(); } + + function defaultStateName() + { + return stateList[defaultStateIndex].title; + } + + function loadStatesFromProject(projectData) + { + if (!projectData.states) + projectData.states = []; + if (projectData.defaultStateIndex !== undefined) + defaultStateIndex = projectData.defaultStateIndex; + else + defaultStateIndex = 0; + var items = projectData.states; + for(var i = 0; i < items.length; i++) { + var item = fromPlainStateItem(items[i]); + stateListModel.append(item); + stateList.push(item); + } + stateListModelReady(); + } } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 5eb3fbb13..4d50db7b1 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -9,7 +9,7 @@ Window { id: modalTransactionDialog modality: Qt.WindowModal width:640 - height:480 + height:640 visible: false property int transactionIndex @@ -21,10 +21,12 @@ Window { property var itemParams; property bool isConstructorTransaction; property bool useTransactionDefaultValue: false + property var qType; signal accepted; function open(index, item) { + qType = []; rowFunction.visible = !useTransactionDefaultValue; rowValue.visible = !useTransactionDefaultValue; rowGas.visible = !useTransactionDefaultValue; @@ -68,6 +70,7 @@ Window { } function loadParameters() { + paramsModel.clear(); if (!paramsModel) return; if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { @@ -75,7 +78,27 @@ Window { var parameters = func.parameters; for (var p = 0; p < parameters.length; p++) { var pname = parameters[p].name; - paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" }); + var varComponent; + var type = parameters[p].type; + + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + + var param = varComponent.createObject(modalTransactionDialog); + var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; + + param.setValue(value); + param.setDeclaration(parameters[p]); + qType.push({ name: pname, value: param }); + paramsModel.append({ name: pname, type: parameters[p].type, value: value }); } } } @@ -85,6 +108,15 @@ Window { visible = false; } + function qTypeParam(name) + { + for (var k in qType) + { + if (qType[k].name === name) + return qType[k].value; + } + } + function getItem() { var item; @@ -109,14 +141,15 @@ Window { if (isConstructorTransaction) item.functionId = qsTr("Constructor"); + var orderedQType = []; for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); - var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); - var param = intComponent.createObject(modalTransactionDialog); - - param.setValue(parameter.value); - item.parameters[parameter.name] = param; + var qtypeParam = qTypeParam(parameter.name); + qtypeParam.setValue(parameter.value); + orderedQType.push(qtypeParam); + item.parameters[parameter.name] = parameter.value; } + item.qType = orderedQType; return item; } @@ -219,8 +252,10 @@ Window { } TableView { model: paramsModel - Layout.fillWidth: true - + Layout.preferredWidth: 120 * 2 + 240 + Layout.minimumHeight: 150 + Layout.preferredHeight: 400 + Layout.maximumHeight: 600 TableViewColumn { role: "name" title: qsTr("Name") @@ -234,12 +269,11 @@ Window { TableViewColumn { role: "value" title: qsTr("Value") - width: 120 + width: 240 } - itemDelegate: { - return editableDelegate; - } + rowDelegate: rowDelegate + itemDelegate: editableDelegate } } } @@ -268,19 +302,15 @@ Window { } Component { - id: editableDelegate + id: rowDelegate Item { + height: 100 + } + } - Text { - width: parent.width - anchors.margins: 4 - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - elide: styleData.elideMode - text: styleData.value !== undefined ? styleData.value : "" - color: styleData.textColor - visible: !styleData.selected - } + Component { + id: editableDelegate + Item { Loader { id: loaderEditor anchors.fill: parent @@ -289,14 +319,87 @@ Window { target: loaderEditor.item onTextChanged: { if (styleData.role === "value" && styleData.row < paramsModel.count) - paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text); + loaderEditor.updateValue(styleData.row, styleData.role, loaderEditor.item.text); } } - sourceComponent: (styleData.selected) ? editor : null + + function updateValue(row, role, value) + { + paramsModel.setProperty(styleData.row, styleData.role, value); + } + + sourceComponent: + { + if (styleData.role === "value") + { + if (paramsModel.get(styleData.row) === undefined) + return null; + if (paramsModel.get(styleData.row).type.indexOf("int") !== -1) + return intViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("bool") !== -1) + return boolViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("string") !== -1) + return stringViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("hash") !== -1) + return hashViewComp; + } + else + return editor; + } + + Component + { + id: intViewComp + QIntTypeView + { + id: intView + text: styleData.value + } + } + + Component + { + id: boolViewComp + QBoolTypeView + { + id: boolView + defaultValue: "1" + Component.onCompleted: + { + loaderEditor.updateValue(styleData.row, styleData.role, + (paramsModel.get(styleData.row).value === "" ? defaultValue : + paramsModel.get(styleData.row).value)); + text = (paramsModel.get(styleData.row).value === "" ? defaultValue : paramsModel.get(styleData.row).value); + } + } + } + + Component + { + id: stringViewComp + QStringTypeView + { + id: stringView + text: styleData.value + } + } + + + Component + { + id: hashViewComp + QHashTypeView + { + id: hashView + text: styleData.value + } + } + Component { id: editor TextInput { id: textinput + readOnly: true color: styleData.textColor text: styleData.value MouseArea { diff --git a/mix/qml/main.qml b/mix/qml/main.qml index b2fc38b0a..720d5070d 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -34,7 +34,7 @@ ApplicationWindow { MenuItem { action: exitAppAction } } Menu { - title: qsTr("Debug") + title: qsTr("Deploy") MenuItem { action: debugRunAction } MenuItem { action: mineAction } MenuSeparator {} @@ -89,9 +89,22 @@ ApplicationWindow { onTriggered: clientModel.mine(); enabled: codeModel.hasContract && !clientModel.running } + + Connections { + target: projectModel.stateListModel + + function updateRunLabel() + { + debugRunAction.text = qsTr("Deploy") + " \"" + projectModel.stateListModel.defaultStateName() + "\""; + } + + onDefaultStateChanged: updateRunLabel() + onStateListModelReady: updateRunLabel() + } + Action { id: debugRunAction - text: qsTr("Run") + text: qsTr("Deploy") shortcut: "F5" onTriggered: mainContent.startQuickDebugging() enabled: codeModel.hasContract && !clientModel.running diff --git a/mix/res.qrc b/mix/res.qrc index b511217e6..d73635f9d 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -42,8 +42,19 @@ <file>qml/Ether.qml</file> <file>qml/EtherValue.qml</file> <file>qml/BigIntValue.qml</file> + <file>qml/QVariableDefinition.qml</file> + <file>qml/QBoolType.qml</file> + <file>qml/QHashType.qml</file> + <file>qml/QIntType.qml</file> + <file>qml/QRealType.qml</file> <file>qml/js/QEtherHelper.js</file> <file>qml/js/TransactionHelper.js</file> + <file>qml/QStringType.qml</file> + <file>qml/QBoolTypeView.qml</file> + <file>qml/QIntTypeView.qml</file> + <file>qml/QRealTypeView.qml</file> + <file>qml/QStringTypeView.qml</file> + <file>qml/QHashTypeView.qml</file> <file>qml/ContractLibrary.qml</file> <file>stdc/config.sol</file> <file>stdc/namereg.sol</file> @@ -51,5 +62,6 @@ <file>qml/TransactionLog.qml</file> <file>res/mix_256x256x32.png</file> <file>qml/CallStack.qml</file> + <file>qml/QVariableDeclaration.qml</file> </qresource> </RCC> diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 7edc250c8..d0d501677 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -92,6 +92,16 @@ BOOST_AUTO_TEST_CASE(multiple_functions) BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes()); } +BOOST_AUTO_TEST_CASE(named_args) +{ + char const* sourceCode = "contract test {\n" + " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" + " function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n" + "}\n"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); +} + BOOST_AUTO_TEST_CASE(while_loop) { char const* sourceCode = "contract test {\n" @@ -885,7 +895,7 @@ BOOST_AUTO_TEST_CASE(constructor) BOOST_AUTO_TEST_CASE(simple_accessor) { char const* sourceCode = "contract test {\n" - " uint256 data;\n" + " uint256 public data;\n" " function test() {\n" " data = 8;\n" " }\n" @@ -897,10 +907,10 @@ BOOST_AUTO_TEST_CASE(simple_accessor) BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { char const* sourceCode = "contract test {\n" - " uint256 data;\n" - " string6 name;\n" - " hash a_hash;\n" - " address an_address;\n" + " uint256 public data;\n" + " string6 public name;\n" + " hash public a_hash;\n" + " address public an_address;\n" " function test() {\n" " data = 8;\n" " name = \"Celina\";\n" @@ -908,7 +918,6 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) " an_address = address(0x1337);\n" " super_secret_data = 42;\n" " }\n" - " private:" " uint256 super_secret_data;" "}\n"; compileAndRun(sourceCode); @@ -919,6 +928,27 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); } +BOOST_AUTO_TEST_CASE(complex_accessors) +{ + char const* sourceCode = "contract test {\n" + " mapping(uint256 => string4) public to_string_map;\n" + " mapping(uint256 => bool) public to_bool_map;\n" + " mapping(uint256 => uint256) public to_uint_map;\n" + " mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map;\n" + " function test() {\n" + " to_string_map[42] = \"24\";\n" + " to_bool_map[42] = false;\n" + " to_uint_map[42] = 12;\n" + " to_multiple_map[42][23] = 31;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24")); + BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false)); + BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12)); + BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31)); +} + BOOST_AUTO_TEST_CASE(balance) { char const* sourceCode = "contract test {\n" @@ -1490,8 +1520,7 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor) setName("abc"); } function getName() returns (string3 ret) { return name; } - private: - function setName(string3 _name) { name = _name; } + function setName(string3 _name) private { name = _name; } })"; compileAndRun(sourceCode); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index b9a7140f7..1a087592c 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -467,6 +467,24 @@ BOOST_AUTO_TEST_CASE(illegal_override_indirect) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(illegal_override_visibility) +{ + char const* text = R"( + contract B { function f() protected {} } + contract C is B { function f() public {} } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(illegal_override_constness) +{ + char const* text = R"( + contract B { function f() constant {} } + contract C is B { function f() {} } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(complex_inheritance) { char const* text = R"( @@ -636,7 +654,9 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) " function fun() {\n" " uint64(2);\n" " }\n" - "uint256 foo;\n" + "uint256 public foo;\n" + "mapping(uint=>string4) public map;\n" + "mapping(uint=>mapping(uint=>string4)) public multiple_map;\n" "}\n"; ASTPointer<SourceUnit> source; @@ -644,10 +664,27 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr); FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); - BOOST_REQUIRE(function->hasDeclaration()); + BOOST_REQUIRE(function && function->hasDeclaration()); auto returnParams = function->getReturnParameterTypeNames(); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK(function->isConstant()); + + function = retrieveFunctionBySignature(contract, "map(uint256)"); + BOOST_REQUIRE(function && function->hasDeclaration()); + auto params = function->getParameterTypeNames(); + BOOST_CHECK_EQUAL(params.at(0), "uint256"); + returnParams = function->getReturnParameterTypeNames(); + BOOST_CHECK_EQUAL(returnParams.at(0), "string4"); + BOOST_CHECK(function->isConstant()); + + function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)"); + BOOST_REQUIRE(function && function->hasDeclaration()); + params = function->getParameterTypeNames(); + BOOST_CHECK_EQUAL(params.at(0), "uint256"); + BOOST_CHECK_EQUAL(params.at(1), "uint256"); + returnParams = function->getReturnParameterTypeNames(); + BOOST_CHECK_EQUAL(returnParams.at(0), "string4"); + BOOST_CHECK(function->isConstant()); } BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) @@ -668,16 +705,19 @@ BOOST_AUTO_TEST_CASE(private_state_variable) " function fun() {\n" " uint64(2);\n" " }\n" - "private:\n" - "uint256 foo;\n" + "uint256 private foo;\n" + "uint256 protected bar;\n" "}\n"; ASTPointer<SourceUnit> source; ContractDefinition const* contract; BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr); - FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); + FunctionTypePointer function; + function = retrieveFunctionBySignature(contract, "foo()"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); + function = retrieveFunctionBySignature(contract, "bar()"); + BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a protected variable should not exist"); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -780,6 +820,54 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(access_to_default_function_visibility) +{ + char const* text = R"( + contract c { + function f() {} + } + contract d { + function g() { c(0).f(); } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(access_to_protected_function) +{ + char const* text = R"( + contract c { + function f() protected {} + } + contract d { + function g() { c(0).f(); } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) +{ + char const* text = R"( + contract c { + uint a; + } + contract d { + function g() { c(0).a(); } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(access_to_protected_state_variable) +{ + char const* text = R"( + contract c { + uint public a; + } + contract d { + function g() { c(0).a(); } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 4adee9c66..4ccdcd57a 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -129,9 +129,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) ASTPointer<ContractDefinition> contract; ASTPointer<FunctionDefinition> function; char const* text = "contract test {\n" - " private:\n" - " uint256 stateVar;\n" - " public:\n" + " uint256 stateVar;\n" " /// This is a test function\n" " function functionName(hash hashin) returns (hash hashout) {}\n" "}\n"; @@ -162,9 +160,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) ASTPointer<ContractDefinition> contract; ASTPointer<FunctionDefinition> function; char const* text = "contract test {\n" - " private:\n" " uint256 stateVar;\n" - " public:\n" " /// This is test function 1\n" " function functionName1(hash hashin) returns (hash hashout) {}\n" " /// This is test function 2\n" @@ -621,6 +617,31 @@ BOOST_AUTO_TEST_CASE(event_arguments_indexed) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(visibility_specifiers) +{ + char const* text = R"( + contract c { + uint private a; + uint protected b; + uint public c; + uint d; + function f() {} + function f_priv() private {} + function f_public() public {} + function f_protected() protected {} + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) +{ + char const* text = R"( + contract c { + uint private protected a; + })"; + BOOST_CHECK_THROW(parseText(text), ParserError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/stateOriginal.cpp b/test/stateOriginal.cpp index f4804c43b..b1a7c0d8e 100644 --- a/test/stateOriginal.cpp +++ b/test/stateOriginal.cpp @@ -51,7 +51,7 @@ int stateTest() cout << s; // Mine to get some ether! - s.commitToMine(); + s.commitToMine(bc); while (!s.mine(100).completed) {} s.completeMine(); bc.attemptImport(s.blockData(), stateDB); @@ -74,8 +74,9 @@ int stateTest() cout << s; // Mine to get some ether and set in stone. - s.commitToMine(); - while (!s.mine(100).completed) {} + s.commitToMine(bc); + s.commitToMine(bc); + while (!s.mine(50).completed) { s.commitToMine(bc); } s.completeMine(); bc.attemptImport(s.blockData(), stateDB);