diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index f20782a42..3061b07ef 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1206,8 +1206,9 @@ string Main::renderDiff(StateDiff const& _d) const if (ad.balance) { - s << "
" << indent << "Balance " << dec << formatBalance(ad.balance.to()); - s << " " << showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << noshowpos << ""; + s << "
" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]"; + auto d = (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())); + s << " " << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << ""; } if (ad.nonce) { @@ -1216,7 +1217,7 @@ string Main::renderDiff(StateDiff const& _d) const } if (ad.code) { - s << "
" << indent << "Code " << hex << ad.code.to().size() << " bytes"; + s << "
" << indent << "Code " << dec << ad.code.to().size() << " bytes"; if (ad.code.from().size()) s << " (" << ad.code.from().size() << " bytes)"; } diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 88e2a3e16..427e0a9c4 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -71,8 +71,9 @@ macro(eth_install_executable EXECUTABLE) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app ${eth_qml_dir} + COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir} WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents ) # This tool and next will inspect linked libraries in order to determine which dependencies are required @@ -82,19 +83,11 @@ macro(eth_install_executable EXECUTABLE) set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") endif () - # TODO check, how fixup_bundle works and if it is required install(CODE " include(BundleUtilities) set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") + verify_app(\"${APP_BUNDLE_PATH}\") " COMPONENT RUNTIME ) - # Cleanup duplicate libs from macdeployqt - install(CODE " - file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\") - if (LINGER_RM) - file(REMOVE \${LINGER_RM}) - endif () - ") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # copy all dlls to executable directory 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> 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> 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 0f7fb64c6..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)) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 5232144c2..3f81cd4c9 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -682,8 +682,6 @@ LogBloom State::logBloom() const return ret; } -// @returns the block that represents the difference between m_previousBlock and m_currentBlock. -// (i.e. all the transactions we executed). void State::commitToMine(BlockChain const& _bc) { uncommitToMine(); @@ -802,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 85abd9366..0a288238d 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -122,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(blockchain); + * 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 817b55852..fa4bcc591 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); -},{"./abi":1,"./utils":11}],5:[function(require,module,exports){ + 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":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,13 +683,16 @@ 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* Filter.prototype.arrived = function(callback) { this.changed(callback); }; +Filter.prototype.happened = function(callback) { + this.changed(callback); +}; /// gets called when there is new eth/shh message Filter.prototype.changed = function(callback) { @@ -600,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); } } }; @@ -623,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. @@ -779,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. @@ -812,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; @@ -868,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 . */ +/** @file jsonrpc.js + * @authors: + * Marek Kotewicz + * @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 !== undefined; // only undefined is not valid json object +}; + +/// 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 . +*/ /** @file providermanager.js * @authors: * Jeffrey Wilcke @@ -877,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 @@ -891,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); }; @@ -917,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; } @@ -963,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. @@ -991,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. @@ -1078,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. @@ -1101,6 +1258,8 @@ module.exports = { * @date 2015 */ +var c = require('./const'); + /// Finds first index of array element matching pattern /// @param array /// @param callback pattern @@ -1163,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 @@ -1182,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, @@ -1189,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. @@ -1225,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 [ @@ -1354,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 }); }; }); @@ -1368,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] }); }; } @@ -1409,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: { @@ -1467,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 @@ -1494,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(); @@ -1514,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 81a7e3747..118372970 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;;AC/FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \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 .\n*/\n/** @file const.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file event.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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};\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 .\n*/\n/** @file const.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file event.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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 .\n*/\n/** @file formatters.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file httpsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \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 .\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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 .\n*/\n/** @file qtsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \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 .\n*/\n/** @file httpsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \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 .\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz \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 !== undefined; // only undefined is not valid json object\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 .\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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 .\n*/\n/** @file qtsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \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 .\n*/\n/** @file types.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file utils.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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 .\n*/\n/** @file utils.js\n * @authors:\n * Marek Kotewicz \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 .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \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 cc9b205d1..a724e6261 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;av;v++)g.push(h(e.slice(0,r))),e=e.slice(r);n.push(g)}else i.prefixedType("string")(t[s].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":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),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&&!s.constant,g=h.collapse!==!1;if(t._options={},t._isTransact=null,d)return a({abi:e,address:o,method:s.name,params:i}),void n.eth.transact(h);var v=n.eth.call(h),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.changed=function(t){this.callbacks.push(t)},r.prototype.trigger=function(t){for(var e=0;en;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;n2?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&&nv;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;rn;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;n3e3&&r2?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 @@ + + + + + + + + + +
+ +
+
+ +
+
+
+ + 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 4cb297f37..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,13 +56,16 @@ 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* Filter.prototype.arrived = function(callback) { this.changed(callback); }; +Filter.prototype.happened = function(callback) { + this.changed(callback); +}; /// gets called when there is new eth/shh message Filter.prototype.changed = function(callback) { @@ -71,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..b2d6922c0 --- /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 . +*/ +/** @file jsonrpc.js + * @authors: + * Marek Kotewicz + * @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 !== undefined; // only undefined is not valid json object +}; + +/// 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..920b5f3a9 --- /dev/null +++ b/libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js @@ -0,0 +1,143 @@ +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); + }); + + it('should validate jsonrpc response with result field === 0', function () { + + // given + var response = { + jsonrpc: '2.0', + id: 1, + result: 0 + }; + + // 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/libjsqrc/natspec.js b/libjsqrc/natspec.js index d0bbdff17..c8cf07496 100644 --- a/libjsqrc/natspec.js +++ b/libjsqrc/natspec.js @@ -29,10 +29,20 @@ var getContractMethods = function (address, abi) { return web3.eth.contract(address, abi); }; +var getMethodWithName = function(abi, name) { + for (var i = 0; i < abi.length; i++) { + if (abi[i].name === name) { + return abi[i]; + } + } + console.warn('could not find method with name: ' + name); + return undefined; +}; + /// Function called to get all contract method input variables /// @returns hashmap with all contract's method input variables var getContractInputParams = function (abi, methodName, params) { - var method = web3.abi.getMethodWithName(abi, methodName); + var method = getMethodWithName(abi, methodName); return method.inputs.reduce(function (acc, current, index) { acc[current.name] = params[index]; return acc; 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 const& _name): - ASTNode(_location), m_name(_name), m_scope(nullptr) {} + Declaration(Location const& _location, ASTPointer 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 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 const& _name, - bool _isPublic, - bool _isConstructor, + Declaration::Visibility _visibility, bool _isConstructor, ASTPointer const& _documentation, ASTPointer const& _parameters, bool _isDeclaredConst, std::vector> const& _modifiers, ASTPointer const& _returnParameters, ASTPointer 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> const& getModifiers() const { return m_functionModifiers; } @@ -371,7 +378,6 @@ public: std::string getCanonicalSignature() const; private: - bool m_isPublic; bool m_isConstructor; ASTPointer m_parameters; bool m_isDeclaredConst; @@ -388,10 +394,10 @@ class VariableDeclaration: public Declaration { public: VariableDeclaration(Location const& _location, ASTPointer const& _type, - ASTPointer 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 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(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 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 const& _expression, - std::vector> const& _arguments): - Expression(_location), m_expression(_expression), m_arguments(_arguments) {} + std::vector> const& _arguments, std::vector> 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> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } + std::vector> 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 m_expression; std::vector> m_arguments; + std::vector> 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 #include +#include #include #include #include @@ -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(*_functionCall.getExpression().getType()); - vector> arguments = _functionCall.getArguments(); - solAssert(arguments.size() == function.getParameterTypes().size(), ""); + TypePointers const& parameterTypes = function.getParameterTypes(); + vector> const& callArguments = _functionCall.getArguments(); + vector> const& callArgumentNames = _functionCall.getNames(); + solAssert(callArguments.size() == parameterTypes.size(), ""); + + vector> 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> 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 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 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 Parser::parseInheritanceSpecifier() return nodeFactory.createNode(name, arguments); } -ASTPointer 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 Parser::parseFunctionDefinition(ASTString const* _contractName) { ASTNodeFactory nodeFactory(*this); ASTPointer docstring; @@ -201,16 +208,24 @@ ASTPointer Parser::parseFunctionDefinition(bool _isPublic, A name = expectIdentifierToken(); ASTPointer parameters(parseParameterList()); bool isDeclaredConst = false; + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); vector> 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 Parser::parseFunctionDefinition(bool _isPublic, A ASTPointer block = parseBlock(); nodeFactory.setEndPositionFromNode(block); bool const c_isConstructor = (_contractName && *name == *_contractName); - return nodeFactory.createNode(name, _isPublic, c_isConstructor, docstring, + return nodeFactory.createNode(name, visibility, c_isConstructor, docstring, parameters, isDeclaredConst, modifiers, returnParameters, block); } @@ -253,14 +268,18 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp ASTNodeFactory nodeFactory(*this); ASTPointer 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(type, expectIdentifierToken(), - _options.isPublic, _options.isStateVariable, + visibility, _options.isStateVariable, isIndexed); } @@ -313,7 +332,7 @@ ASTPointer 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 Parser::parseBinaryExpression(int _minPrecedence) ASTPointer 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 Parser::parseBinaryExpression(int _minPrecedence) nodeFactory.setEndPositionFromNode(right); expression = nodeFactory.createNode(expression, op, right); } - } return expression; } @@ -648,10 +665,12 @@ ASTPointer Parser::parseLeftHandSideExpression() case Token::LPAREN: { m_scanner->next(); - vector> arguments = parseFunctionCallArguments(); + vector> arguments; + vector> names; + std::tie(arguments, names) = parseFunctionCallArguments(); nodeFactory.markEndPosition(); expectToken(Token::RPAREN); - expression = nodeFactory.createNode(expression, arguments); + expression = nodeFactory.createNode(expression, arguments, names); } break; default: @@ -704,7 +723,7 @@ ASTPointer Parser::parsePrimaryExpression() return expression; } -vector> Parser::parseFunctionCallArguments() +vector> Parser::parseFunctionCallListArguments() { vector> arguments; if (m_scanner->getCurrentToken() != Token::RPAREN) @@ -719,6 +738,32 @@ vector> Parser::parseFunctionCallArguments() return arguments; } +pair>, vector>> Parser::parseFunctionCallArguments() +{ + pair>, vector>> 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 parseImportDirective(); ASTPointer parseContractDefinition(); ASTPointer parseInheritanceSpecifier(); - ASTPointer parseFunctionDefinition(bool _isPublic, ASTString const* _contractName); + Declaration::Visibility parseVisibilitySpecifier(Token::Value _token); + ASTPointer parseFunctionDefinition(ASTString const* _contractName); ASTPointer parseStructDefinition(); ASTPointer parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); ASTPointer parseModifierDefinition(); @@ -81,7 +81,8 @@ private: ASTPointer parseUnaryExpression(); ASTPointer parseLeftHandSideExpression(); ASTPointer parsePrimaryExpression(); - std::vector> parseFunctionCallArguments(); + std::vector> parseFunctionCallListArguments(); + std::pair>, std::vector>> 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 paramNames({}); - TypePointers retParams({_varDecl.getType()}); - vector retParamNames({ _varDecl.getName()}); - // for now, no input parameters LTODO: change for some things like mapping + TypePointers params; + vector paramNames; + TypePointers retParams; + vector retParamNames; + TypePointer varDeclType = _varDecl.getType(); + auto mappingType = dynamic_cast(varDeclType.get()); + auto returnType = varDeclType; + + while (mappingType != nullptr) + { + params.push_back(mappingType->getKeyType()); + paramNames.push_back(""); + returnType = mappingType->getValueType(); + mappingType = dynamic_cast(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/macdeployfix.sh b/macdeployfix.sh new file mode 100755 index 000000000..9a6ce1ebc --- /dev/null +++ b/macdeployfix.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# solves problem with macdeployqt on Qt 5.4 RC +# http://qt-project.org/forums/viewthread/50118 + +BUILD_FOLDER_PATH=$1 +BUILD_QML_FOLDER_PATH="$BUILD_FOLDER_PATH/Resources/qml" +BUILD_PLUGINS_FOLDER_PATH="$BUILD_FOLDER_PATH/PlugIns" + +if [ ! -d ${BUILD_QML_FOLDER_PATH} ]; then + # we are not using any qml files + # gracefully exit + exit 0 +fi + +declare -a BROKEN_FILES; +k=0; +for j in $(find ${BUILD_QML_FOLDER_PATH} -name *.dylib); do + BROKEN_FILES[${k}]=$j + + ((k=k+1)) +done + + +for i in "${BROKEN_FILES[@]}"; do + REPLACE_STRING="$BUILD_FOLDER_PATH/" + APP_CONTENT_FILE=${i//$REPLACE_STRING/""} + IFS='/' read -a array <<< "$APP_CONTENT_FILE" + LENGTH=${#array[@]} + LAST_ITEM_INDEX=$((LENGTH-1)) + FILE=${array[${LENGTH} - 1]} + + ORIGINE_PATH=$(find ${BUILD_PLUGINS_FOLDER_PATH} -name ${FILE}) + ORIGINE_PATH=${ORIGINE_PATH//$REPLACE_STRING/""} + s="" + for((l=0;l<${LAST_ITEM_INDEX};l++)) do + s=$s"../" + done + s=$s$ORIGINE_PATH + echo "s: $s" + + REMOVE_BROKEN_ALIAS=$(rm -rf $i) + RESULT=$(ln -s $s $i) +done + diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index ad9c78e9b..4f7c494e8 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -27,15 +27,16 @@ #include #include #include -#include +#include #include "CodeModel.h" #include "FileIo.h" #include "ClientModel.h" #include "CodeEditorExtensionManager.h" #include "Exceptions.h" -#include "AppContext.h" #include "QEther.h" +#include "QVariableDefinition.h" #include "HttpServer.h" +#include "AppContext.h" using namespace dev; using namespace dev::eth; @@ -63,6 +64,12 @@ void AppContext::load() m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); qmlRegisterType("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); + qmlRegisterType("org.ethereum.qml.QIntType", 1, 0, "QIntType"); + qmlRegisterType("org.ethereum.qml.QRealType", 1, 0, "QRealType"); + qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); + qmlRegisterType("org.ethereum.qml.QHashType", 1, 0, "QHashType"); + qmlRegisterType("org.ethereum.qml.QBoolType", 1, 0, "QBoolType"); + qmlRegisterType("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) @@ -76,7 +83,7 @@ void AppContext::load() qmlRegisterType("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); qmlRegisterType("HttpServer", 1, 0, "HttpServer"); m_applicationEngine->load(QUrl("qrc:/qml/main.qml")); - QQuickWindow *window = qobject_cast(m_applicationEngine->rootObjects().at(0)); + QWindow *window = qobject_cast(m_applicationEngine->rootObjects().at(0)); window->setIcon(QIcon(":/res/mix_256x256x32.png")); appLoaded(); } diff --git a/mix/AssemblyDebuggerControl.cpp b/mix/AssemblyDebuggerControl.cpp index e065513a8..7bf177981 100644 --- a/mix/AssemblyDebuggerControl.cpp +++ b/mix/AssemblyDebuggerControl.cpp @@ -20,7 +20,6 @@ #include #include #include -#include "AppContext.h" #include "ClientModel.h" #include "AssemblyDebuggerControl.h" diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index f1b837f01..d5574667a 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -26,6 +26,8 @@ else() qt5_add_resources(UI_RESOURCES noweb.qrc) endif() +add_definitions(-DQT_QML_DEBUG) + # eth_add_executable is defined in cmake/EthExecutableHelper.cmake eth_add_executable(${EXECUTABLE} ICON mix diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 914edf52d..4ce7b7755 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -30,6 +30,7 @@ #include "Exceptions.h" #include "QContractDefinition.h" #include "QVariableDeclaration.h" +#include "QVariableDefinition.h" #include "ContractCallDataEncoder.h" #include "CodeModel.h" #include "ClientModel.h" @@ -66,6 +67,10 @@ ClientModel::ClientModel(AppContext* _context): m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()), m_contractAddress(Address()) { qRegisterMetaType("QBigInt*"); + qRegisterMetaType("QIntType*"); + qRegisterMetaType("QStringType*"); + qRegisterMetaType("QRealType*"); + qRegisterMetaType("QHashType*"); qRegisterMetaType("QEther*"); qRegisterMetaType("QVariableDefinition*"); qRegisterMetaType("QVariableDefinitionList*"); @@ -93,8 +98,16 @@ ClientModel::~ClientModel() QString ClientModel::apiCall(QString const& _message) { - m_rpcConnector->OnRequest(_message.toStdString(), nullptr); - return m_rpcConnector->response(); + try + { + m_rpcConnector->OnRequest(_message.toStdString(), nullptr); + return m_rpcConnector->response(); + } + catch (...) + { + std::cerr << boost::current_exception_diagnostic_information(); + return QString(); + } } void ClientModel::mine() @@ -138,13 +151,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(p.value()); - transactionSettings.parameterValues.insert(std::make_pair(p.key(), boost::get(param->internalValue()))); + QVariableDefinition* param = qvariant_cast(variant); + transactionSettings.parameterValues.push_back(param); } if (transaction.value("executeConstructor").toBool()) @@ -204,14 +217,11 @@ void ClientModel::executeSequence(std::vector 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()) @@ -322,11 +332,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; @@ -355,6 +360,9 @@ void ClientModel::onNewTransaction() function = QObject::tr(""); } + 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(); @@ -364,7 +372,13 @@ void ClientModel::onNewTransaction() { QFunctionDefinition* funcDef = def->getFunction(functionHash); if (funcDef) + { function = funcDef->name(); + ContractCallDataEncoder encoder; + QList 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 63731badf..493290780 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -26,7 +26,7 @@ #include #include #include -#include "MixClient.h" +#include "MachineStates.h" namespace dev { @@ -38,6 +38,8 @@ class Web3Server; class RpcConnector; class QEther; class QDebugData; +class MixClient; +class QVariableDefinition; /// Backend transaction config class struct TransactionSettings @@ -59,7 +61,7 @@ struct TransactionSettings /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value - std::map parameterValues; + QList 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 . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @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 ContractCallDataEncoder::decode(QList _returnParameters, bytes _value) +QList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes _value) { QList 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 decode(QList _dec, bytes _value); + QList decode(QList 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 QmlErrorInfo; typedef boost::error_info FileError; diff --git a/mix/MachineStates.h b/mix/MachineStates.h new file mode 100644 index 000000000..d19fd9b74 --- /dev/null +++ b/mix/MachineStates.h @@ -0,0 +1,79 @@ +/* +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 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 . +*/ +/** @file MixClient.h +* @author Yann yann@ethdev.com +* @author Arkadiy Paronyan arkadiy@ethdev.com +* @date 2015 +* Ethereum IDE client. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace dev +{ +namespace mix +{ + + /** + * @brief Store information about a machine state. + */ + struct MachineState + { + uint64_t steps; + dev::Address address; + dev::u256 curPC; + dev::eth::Instruction inst; + dev::bigint newMemSize; + dev::u256 gas; + dev::u256s stack; + dev::bytes memory; + dev::bigint gasCost; + std::map storage; + std::vector levels; + unsigned codeIndex; + unsigned dataIndex; + }; + + /** + * @brief Store information about a machine states. + */ + struct ExecutionResult + { + ExecutionResult() : receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} + + std::vector machineStates; + std::vector transactionData; + std::vector executionCode; + bytes returnValue; + dev::Address address; + dev::Address sender; + dev::Address contractAddress; + dev::u256 value; + dev::eth::TransactionReceipt receipt; + }; + + using ExecutionResults = std::vector; +} +} \ No newline at end of file diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 7d377981e..a6c833532 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -50,12 +50,15 @@ void MixClient::resetState(u256 _balance) Guard fl(m_filterLock); m_filters.clear(); m_watches.clear(); - m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty); + m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Genesis); m_state.addBalance(m_userAccount.address(), _balance); Block genesis; 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; } void MixClient::executeTransaction(Transaction const& _t, State& _state) @@ -159,11 +162,15 @@ void MixClient::mine() { WriteGuard l(x_state); Block& block = m_blocks.back(); + m_state.mine(0, true); m_state.completeMine(); + m_state.commitToMine(BlockChain()); + m_state.cleanup(true); block.state = m_state; block.info = m_state.info(); block.hash = block.info.hash; m_blocks.push_back(Block()); + h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; noteChanged(changed); } diff --git a/mix/MixClient.h b/mix/MixClient.h index fede1891e..c34fff60b 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -26,52 +26,13 @@ #include #include #include +#include "MachineStates.h" namespace dev { namespace mix { -/** - * @brief Store information about a machine state. - */ -struct MachineState -{ - uint64_t steps; - dev::Address address; - dev::u256 curPC; - dev::eth::Instruction inst; - dev::bigint newMemSize; - dev::u256 gas; - dev::u256s stack; - dev::bytes memory; - dev::bigint gasCost; - std::map storage; - std::vector levels; - unsigned codeIndex; - unsigned dataIndex; -}; - -/** - * @brief Store information about a machine states. - */ -struct ExecutionResult -{ - ExecutionResult(): receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} - - std::vector machineStates; - std::vector transactionData; - std::vector executionCode; - bytes returnValue; - dev::Address address; - dev::Address sender; - dev::Address contractAddress; - dev::u256 value; - dev::eth::TransactionReceipt receipt; -}; - -using ExecutionResults = std::vector; - struct Block { ExecutionResults transactions; 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; +using BigIntVariant = boost::variant; struct add: public boost::static_visitor { @@ -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 +#include #include #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 +#include #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(_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 +#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 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/Web3Server.cpp b/mix/Web3Server.cpp index ead2c792f..edac252fe 100644 --- a/mix/Web3Server.cpp +++ b/mix/Web3Server.cpp @@ -57,8 +57,6 @@ void Web3Server::put(std::string const& _name, std::string const& _key, std::str Json::Value Web3Server::eth_changed(int const& _id) { - cnote << "eth_changed(" << _id << ") ->" << client()->peekWatch(_id).size(); - return WebThreeStubServerBase::eth_changed(_id); } diff --git a/mix/main.cpp b/mix/main.cpp index f7213f0fc..d0a19cfb5 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,6 +35,7 @@ int main(int _argc, char* _argv[]) //work around ubuntu appmenu-qt5 bug //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 putenv((char*)"QT_QPA_PLATFORMTHEME="); + putenv((char*)"QSG_RENDER_LOOP=threaded"); #endif try { diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 1ed1c11d2..247de143f 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -23,14 +23,20 @@ Rectangle { property alias rightViewVisible : rightView.visible property alias webViewVisible : webPreview.visible + property alias projectViewVisible : projectList.visible + property alias runOnProjectLoad : mainSettings.runOnProjectLoad property bool webViewHorizontal : codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally - - onWidthChanged: - { - if (rightView.visible) - contentView.width = parent.width - projectList.width - rightView.width; - else - contentView.width = parent.width - projectList.width; + property bool firstCompile: true + + Connections { + target: codeModel + onCompilationComplete: { + if (firstCompile) { + firstCompile = false; + if (codeModel.code.successful && runOnProjectLoad) + startQuickDebugging(); + } + } } function startQuickDebugging() @@ -40,15 +46,11 @@ Rectangle { } function toggleRightView() { - if (!rightView.visible) - rightView.show(); - else - rightView.hide(); + rightView.visible = !rightView.visible; } function ensureRightView() { - if (!rightView.visible) - rightView.show(); + rightView.visible = true; } function rightViewIsVisible() @@ -65,6 +67,10 @@ Rectangle { webPreview.visible = !webPreview.visible; } + function toggleProjectView() { + projectList.visible = !projectList.visible; + } + function toggleWebPreviewOrientation() { codeWebSplitter.orientation = (codeWebSplitter.orientation === Qt.Vertical ? Qt.Horizontal : Qt.Vertical); } @@ -75,19 +81,18 @@ Rectangle { } Settings { - id: mainLayoutSettings + id: mainSettings property alias codeWebOrientation: codeWebSplitter.orientation property alias webWidth: webPreview.width property alias webHeight: webPreview.height + property alias showProjectView: projectList.visible + property bool runOnProjectLoad: false } - GridLayout + ColumnLayout { anchors.fill: parent - rows: 2 - flow: GridLayout.TopToBottom - columnSpacing: 0 - rowSpacing: 0 + spacing: 0 Rectangle { width: parent.width height: 50 @@ -128,116 +133,90 @@ Rectangle { property alias rightViewWidth: rightView.width } - ProjectList { - anchors.left: parent.left - id: projectList - width: 200 - height: parent.height - Layout.minimumWidth: 200 - } - - Splitter + SplitView { - id: resizeLeft - itemToStick: projectList - itemMinimumWidth: projectList.Layout.minimumWidth - direction: "right" - brother: contentView - color: "#a2a2a2" - } - - Rectangle { - anchors.left: projectList.right - id: contentView - width: parent.width - projectList.width - height: parent.height - SplitView { - handleDelegate: Rectangle { - width: 4 - height: 4 - color: "#cccccc" - } - id: codeWebSplitter - anchors.fill: parent - orientation: Qt.Vertical - CodeEditorView { - height: parent.height * 0.6 - anchors.top: parent.top - Layout.fillWidth: true - Layout.fillHeight: true - } - WebPreview { - id: webPreview - height: parent.height * 0.4 - Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical - Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal - Layout.minimumHeight: 200 - Layout.minimumWidth: 200 - } + anchors.fill: parent + handleDelegate: Rectangle { + width: 4 + height: 4 + color: "#cccccc" } - } - - Splitter - { - id: resizeRight - visible: false; - itemToStick: rightView - itemMinimumWidth: rightView.Layout.minimumWidth - direction: "left" - brother: contentView - color: "#a2a2a2" - } - - Rectangle { - visible: false; - id: rightView; + orientation: Qt.Horizontal - Keys.onEscapePressed: hide() - - function show() { - visible = true; - resizeRight.visible = true; - contentView.width = parent.width - projectList.width - rightView.width; + ProjectList { + id: projectList + width: 200 + Layout.minimumWidth: 180 + Layout.fillHeight: true } - - function hide() { - resizeRight.visible = false; - visible = false; - contentView.width = parent.width - projectList.width; + Rectangle { + id: contentView + Layout.fillHeight: true + Layout.fillWidth: true + SplitView { + handleDelegate: Rectangle { + width: 4 + height: 4 + color: "#cccccc" + } + id: codeWebSplitter + anchors.fill: parent + orientation: Qt.Vertical + CodeEditorView { + height: parent.height * 0.6 + anchors.top: parent.top + Layout.fillWidth: true + Layout.fillHeight: true + } + WebPreview { + id: webPreview + height: parent.height * 0.4 + Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical + Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal + Layout.minimumHeight: 200 + Layout.minimumWidth: 200 + } + } } - height: parent.height; - width: 515 - Layout.minimumWidth: 515 - anchors.right: parent.right Rectangle { - anchors.fill: parent; - id: rightPaneView - TabView { - id: rightPaneTabs - tabsVisible: true - antialiasing: true - anchors.fill: parent - style: TabViewStyle { - frameOverlap: 1 - tabBar: - Rectangle { + visible: false; + id: rightView; + Layout.fillHeight: true + Keys.onEscapePressed: visible = false + height: parent.height; + width: 515 + Layout.minimumWidth: 515 + anchors.right: parent.right + Rectangle { + anchors.fill: parent; + id: rightPaneView + TabView { + id: rightPaneTabs + tabsVisible: true + antialiasing: true + anchors.fill: parent + style: TabViewStyle { + frameOverlap: 1 + tabBar: + Rectangle { + color: "#ededed" + id: background + } + tab: Rectangle { color: "#ededed" - id: background + implicitWidth: 80 + implicitHeight: 20 + radius: 2 + Text { + anchors.centerIn: parent + text: styleData.title + color: styleData.selected ? "#7da4cd" : "#202020" + } } - tab: Rectangle { - color: "#ededed" - implicitWidth: 80 - implicitHeight: 20 - radius: 2 - Text { - anchors.centerIn: parent - text: styleData.title - color: styleData.selected ? "#7da4cd" : "#202020" + frame: Rectangle { } } - frame: Rectangle { - } } } } diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index 14716483c..49e63e184 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -10,7 +10,8 @@ Item { id: projectModel signal projectClosed - signal projectLoaded(var projectData) + signal projectLoading(var projectData) + signal projectLoaded() signal documentOpened(var document) signal documentRemoved(var documentId) signal documentUpdated(var documentId) //renamed 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/Splitter.qml b/mix/qml/Splitter.qml deleted file mode 100644 index 341dc4450..000000000 --- a/mix/qml/Splitter.qml +++ /dev/null @@ -1,47 +0,0 @@ -import QtQuick 2.2 - -Rectangle { - property variant itemToStick; - property int itemMinimumWidth; - property string direction; - property variant brother; - - Component.onCompleted: - { - if (direction === "left") - anchors.right = itemToStick.left; - else if (direction === "right") - anchors.left = itemToStick.right; - } - - width: 5 - height: parent.height - anchors.top: parent.top; - MouseArea - { - property int startX: 0; - anchors.fill: parent - onPressed: startX = mouseX; - onPositionChanged: - { - parent.x += mouseX; - var diff = 0; - if (direction == "left") - diff = mouseX - startX; - else if (direction == "right") - diff = -(mouseX - startX); - - if (itemMinimumWidth > itemToStick.width - diff) - { - brother.width = brother.width + diff; - itemToStick.width = itemMinimumWidth; - } - else - { - brother.width = brother.width + diff; - itemToStick.width = itemToStick.width - diff; - } - } - cursorShape: Qt.SizeHorCursor - } -} 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 c158112e1..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 = []; } - onProjectLoaded: { - 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/WebPreview.qml b/mix/qml/WebPreview.qml index bd48210ef..e95a85fde 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -86,7 +86,7 @@ Item { updateDocument(documentId, function(i) { pageListModel.set(i, projectModel.getDocument(documentId)) } ) } - onProjectLoaded: { + onProjectLoading: { for (var i = 0; i < target.listModel.count; i++) { var document = target.listModel.get(i); if (document.isHtml) { diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 2cebc121e..5b3e5450f 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -31,6 +31,7 @@ getText = function() { setTextBase64 = function(text) { editor.setValue(window.atob(text)); + editor.getDoc().clearHistory(); editor.focus(); }; diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index ed7ebd3ce..4d501ffca 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -73,7 +73,8 @@ function loadProject(path) { addFile(projectData.files[i]); } projectSettings.lastProjectPath = path; - projectLoaded(projectData); + projectLoading(projectData); + projectLoaded() } function addExistingFile() { @@ -171,8 +172,8 @@ function doCreateProject(title, path) { files: [ contractsFile, indexFile ] }; //TODO: copy from template - fileIo.writeFile(dirPath + indexFile, ""); - fileIo.writeFile(dirPath + contractsFile, "contract MyContract {\n}\n"); + fileIo.writeFile(dirPath + indexFile, "\n\n\n\n\n\n\n"); + fileIo.writeFile(dirPath + contractsFile, "contract Contract {\n}\n"); newProject(projectData); var json = JSON.stringify(projectData, null, "\t"); fileIo.writeFile(projectFile, json); diff --git a/mix/qml/main.qml b/mix/qml/main.qml index a0a4ba423..49d00311f 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -4,6 +4,7 @@ import QtQuick.Controls.Styles 1.1 import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 +import QtQuick.PrivateWidgets 1.1 import Qt.labs.settings 1.0 import org.ethereum.qml.QEther 1.0 @@ -34,16 +35,18 @@ ApplicationWindow { MenuItem { action: exitAppAction } } Menu { - title: qsTr("Debug") + title: qsTr("Deploy") MenuItem { action: debugRunAction } - MenuItem { action: debugResetStateAction } MenuItem { action: mineAction } + MenuSeparator {} + MenuItem { action: toggleRunOnLoadAction } } Menu { title: qsTr("Windows") MenuItem { action: openNextDocumentAction } MenuItem { action: openPrevDocumentAction } MenuSeparator {} + MenuItem { action: toggleProjectNavigatorAction } MenuItem { action: showHideRightPanelAction } MenuItem { action: toggleWebPreviewAction } MenuItem { action: toggleWebPreviewOrientationAction } @@ -82,47 +85,71 @@ ApplicationWindow { Action { id: mineAction - text: "Mine" + text: qsTr("Mine") shortcut: "Ctrl+M" 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: "&Run" + text: qsTr("Deploy") shortcut: "F5" onTriggered: mainContent.startQuickDebugging() enabled: codeModel.hasContract && !clientModel.running } - Action { - id: debugResetStateAction - text: "Reset &State" - shortcut: "F6" - onTriggered: clientModel.resetState(); - } - Action { id: toggleWebPreviewAction - text: "Show Web View" + text: qsTr("Show Web View") shortcut: "F2" checkable: true checked: mainContent.webViewVisible onTriggered: mainContent.toggleWebPreview(); } + Action { + id: toggleProjectNavigatorAction + text: qsTr("Show Project Navigator") + shortcut: "Alt+0" + checkable: true + checked: mainContent.projectViewVisible + onTriggered: mainContent.toggleProjectView(); + } + Action { id: toggleWebPreviewOrientationAction - text: "Horizontal Web View" + text: qsTr("Horizontal Web View") shortcut: "" checkable: true checked: mainContent.webViewHorizontal onTriggered: mainContent.toggleWebPreviewOrientation(); } + Action { + id: toggleRunOnLoadAction + text: qsTr("Load State on Startup") + shortcut: "" + checkable: true + checked: mainContent.runOnProjectLoad + onTriggered: mainContent.runOnProjectLoad = !mainContent.runOnProjectLoad + } + Action { id: showHideRightPanelAction - text: "Show Right View" + text: qsTr("Show Right View") shortcut: "F7" checkable: true checked: mainContent.rightViewVisible diff --git a/mix/res.qrc b/mix/res.qrc index 639881e6a..d73635f9d 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -42,9 +42,19 @@ qml/Ether.qml qml/EtherValue.qml qml/BigIntValue.qml + qml/QVariableDefinition.qml + qml/QBoolType.qml + qml/QHashType.qml + qml/QIntType.qml + qml/QRealType.qml qml/js/QEtherHelper.js qml/js/TransactionHelper.js - qml/Splitter.qml + qml/QStringType.qml + qml/QBoolTypeView.qml + qml/QIntTypeView.qml + qml/QRealTypeView.qml + qml/QStringTypeView.qml + qml/QHashTypeView.qml qml/ContractLibrary.qml stdc/config.sol stdc/namereg.sol @@ -52,5 +62,6 @@ qml/TransactionLog.qml res/mix_256x256x32.png qml/CallStack.qml + qml/QVariableDeclaration.qml diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 7edc250c8..f248a5a07 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -92,6 +92,26 @@ 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(disorder_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({c: 3, a: 1, b: 2}); }\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 +905,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 +917,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 +928,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 +938,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 +1530,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 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 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..9ba38a4a1 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -124,14 +124,30 @@ BOOST_AUTO_TEST_CASE(single_function_param) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) +{ + char const* text = "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({: 1, : 2, : 3}); }\n" + "}\n"; + BOOST_CHECK_THROW(parseText(text), ParserError); +} + +BOOST_AUTO_TEST_CASE(missing_argument_in_named_args) +{ + char const* text = "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: , b: , c: }); }\n" + "}\n"; + BOOST_CHECK_THROW(parseText(text), ParserError); +} + BOOST_AUTO_TEST_CASE(function_natspec_documentation) { ASTPointer contract; ASTPointer 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 +178,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) ASTPointer contract; ASTPointer 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 +635,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 a49c55061..b1a7c0d8e 100644 --- a/test/stateOriginal.cpp +++ b/test/stateOriginal.cpp @@ -75,7 +75,8 @@ int stateTest() // Mine to get some ether and set in stone. s.commitToMine(bc); - while (!s.mine(100).completed) {} + s.commitToMine(bc); + while (!s.mine(50).completed) { s.commitToMine(bc); } s.completeMine(); bc.attemptImport(s.blockData(), stateDB); diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index 99032d99b..9c88d1b24 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -60,6 +60,7 @@ BOOST_AUTO_TEST_CASE(topic) auto w = whOther->installWatch(BuildTopicMask("odd")); started = true; + set received; for (int iterout = 0, last = 0; iterout < 200 && last < 81; ++iterout) { @@ -67,6 +68,9 @@ BOOST_AUTO_TEST_CASE(topic) { Message msg = wh->envelope(i).open(wh->fullTopic(w)); last = RLP(msg.payload()).toInt(); + if (received.count(last)) + continue; + received.insert(last); cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt(); result += last; }