diff options
author | Taylor Gerring <taylor.gerring@gmail.com> | 2015-02-02 21:22:20 +0800 |
---|---|---|
committer | Taylor Gerring <taylor.gerring@gmail.com> | 2015-02-02 21:22:20 +0800 |
commit | 1e60919d47ac2767706c135332a1a4f79bbf3960 (patch) | |
tree | 3db2f5d5446f451d700bf67ef756d85da0fdda25 /cmd/mist | |
parent | 313cfba7d43529db647789ae826bc426d9da7de3 (diff) | |
parent | 0d97c3ce1322083fb9683a5afec004b2626b620a (diff) | |
download | dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar.gz dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar.bz2 dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar.lz dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar.xz dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.tar.zst dexon-1e60919d47ac2767706c135332a1a4f79bbf3960.zip |
Merge pull request #3 from ethereum/develop
Update to develop
Diffstat (limited to 'cmd/mist')
84 files changed, 6275 insertions, 5108 deletions
diff --git a/cmd/mist/assets/browser.png b/cmd/mist/assets/browser.png Binary files differindex 1d7348170..7b3b0870c 100644 --- a/cmd/mist/assets/browser.png +++ b/cmd/mist/assets/browser.png diff --git a/cmd/mist/assets/debugger/debugger.qml b/cmd/mist/assets/debugger/debugger.qml index b30d20e6b..5566e8fca 100644 --- a/cmd/mist/assets/debugger/debugger.qml +++ b/cmd/mist/assets/debugger/debugger.qml @@ -19,7 +19,7 @@ ApplicationWindow { property alias dataText: rawDataField.text onClosing: { - dbg.Stop() + //dbg.Stop() } menuBar: MenuBar { @@ -353,6 +353,7 @@ ApplicationWindow { ComboBox { + visible: false id: snippets anchors.right: parent.right model: ListModel { diff --git a/cmd/mist/assets/examples/abi.html b/cmd/mist/assets/examples/abi.html new file mode 100644 index 000000000..8d172482c --- /dev/null +++ b/cmd/mist/assets/examples/abi.html @@ -0,0 +1,55 @@ +<!doctype> +<html> +<head> +<title>Hello world</title> +<script src="../ext/bignumber.min.js"></script> +<script src="../ext/ethereum.js/dist/ethereum.js"></script> +<script> + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + var eth = web3.eth; + var desc = [{ + "name": "multiply(uint256)", + "inputs": [{ + "name": "a", + "type": "uint256" + }], + "outputs": [{ + "name": "d", + "type": "uint256" + }] + }]; + var address = web3.eth.transact({ + data: "0x603880600c6000396000f3006001600060e060020a600035048063c6888fa114601857005b6021600435602b565b8060005260206000f35b600081600702905091905056", + gasprice: "1000000000000000", + gas: "10000", + }); + var contract = web3.eth.contract(address, desc); + + function calculate() { + var param = parseInt(document.getElementById('value').value); + + var res = contract.call().multiply(param); + document.getElementById('result').innerText = res.toString(10); + } +</script> +</head> +<body> +<h3>Contract content</h3> +<textarea style="height:100px; width: 300px;" disabled="disabled"> +contract test { + function multiply(uint a) returns(uint d) { + return a * 7; + } +} +</textarea> +<code><pre> +603880600c6000396000f3006001600060e060020a600035048063c6888fa1140 +05b6021600435602b565b8060005260206000f35b600081600702905091905056</pre></code> + +<hr> +<div>7 x <input type="number" id="value" onkeyup='calculate()'></input> = +<span id="result"></spa> + +</body> +</html> diff --git a/cmd/mist/assets/examples/balance.html b/cmd/mist/assets/examples/balance.html new file mode 100644 index 000000000..bc483a879 --- /dev/null +++ b/cmd/mist/assets/examples/balance.html @@ -0,0 +1,40 @@ +<!doctype> +<html> + +<head> +<script src="../ext/bignumber.min.js"></script> +<script src="../ext/ethereum.js/dist/ethereum.js"></script> +<script type="text/javascript"> + + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + + function watchBalance() { + var coinbase = web3.eth.coinbase; + var originalBalance = 0; + + var balance = web3.eth.balanceAt(coinbase); + var originalBalance = web3.toDecimal(balance); + document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...'; + + web3.eth.watch({altered: coinbase}).changed(function() { + balance = web3.eth.balanceAt(coinbase) + var currentBalance = web3.toDecimal(balance); + document.getElementById("current").innerText = 'current: ' + currentBalance; + document.getElementById("diff").innerText = 'diff: ' + (currentBalance - originalBalance); + }); + } + +</script> +</head> +<body> + <h1>coinbase balance</h1> + <button type="button" onClick="watchBalance();">watch balance</button> + <div></div> + <div id="original"></div> + <div id="current"></div> + <div id="diff"></div> +</body> +</html> + + diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html new file mode 100644 index 000000000..edeabe5e8 --- /dev/null +++ b/cmd/mist/assets/examples/coin.html @@ -0,0 +1,98 @@ +<!doctype> +<html> +<title>JevCoin</title> +<head> +<script type="text/javascript" src="../ext/bignumber.min.js"></script> +<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> +</head> +<body> + +<h1>JevCoin</h1> +<div> + <strong>Balance</strong> + <span id="balance"></strong> +</div> + +<div> + <span class="amount">Amount:</span> + <input type="text" id="address" style="width:200px"> + <input type="text" id="amount" style="width:200px"> + <button onclick="transact()">Send</button> +</div> + +<table width="100%" id="table"> +</table> + +</body> + +<script type="text/javascript"> + var web3 = require('web3'); + var eth = web3.eth; + + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + var desc = [{ + "name": "balance(address)", + "inputs": [{ + "name": "who", + "type": "address" + }], + "const": true, + "outputs": [{ + "name": "value", + "type": "uint256" + }] + }, { + "name": "send(address,uint256)", + "inputs": [{ + "name": "to", + "type": "address" + }, { + "name": "value", + "type": "uint256" + }], + "outputs": [] + }]; + + var address = web3.db.get("jevcoin", "address"); + if( address.length == 0 ) { + var code = "0x60056011565b60ae8060356000396000f35b64174876e800600033600160a060020a031660005260205260406000208190555056006001600060e060020a600035048063d0679d34146022578063e3d670d714603457005b602e6004356024356047565b60006000f35b603d600435608d565b8060005260206000f35b80600083600160a060020a0316600052602052604060002090815401908190555080600033600160a060020a031660005260205260406000209081540390819055505050565b6000600082600160a060020a0316600052602052604060002054905091905056"; + address = web3.eth.transact({ + data: code, + gasprice: "1000000000000000", + gas: "10000", + }); + web3.db.put("jevcoin", "address", address); + } + + var contract = web3.eth.contract(address, desc); + + function reflesh() { + document.querySelector("#balance").innerHTML = contract.call().balance(eth.coinbase); + + var table = document.querySelector("#table"); + table.innerHTML = ""; // clear + + var storage = eth.storageAt(address); + for( var item in storage ) { + table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>"; + } + } + + function transact() { + var to = document.querySelector("#address").value; + if( to.length == 0 ) { + to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; + } else { + to = "0x"+to; + } + + var value = parseInt( document.querySelector("#amount").value ); + + contract.transact({gas: "10000", gasprice: eth.gasPrice}).send( to, value ); + } + + reflesh(); +</script> + +</html> + diff --git a/cmd/mist/assets/examples/info.html b/cmd/mist/assets/examples/info.html new file mode 100644 index 000000000..c4df8ea64 --- /dev/null +++ b/cmd/mist/assets/examples/info.html @@ -0,0 +1,72 @@ + +<!doctype> +<html> + +<head> +<script type="text/javascript" src="../ext/bignumber.min.js"></script> +<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> +</head> +<body> + <h1>Info</h1> + + <table width="100%"> + <tr> + <td>Block number</td> + <td id="number"></td> + </tr> + + <tr> + <td>Peer count</td> + <td id="peer_count"></td> + </tr> + + <tr> + <td>Default block</td> + <td id="default_block"></td> + </tr> + + <tr> + <td>Accounts</td> + <td id="accounts"></td> + </tr> + + <tr> + <td>Gas price</td> + <td id="gas_price"></td> + </tr> + + <tr> + <td>Mining</td> + <td id="mining"></td> + </tr> + + <tr> + <td>Listening</td> + <td id="listening"></td> + </tr> + + <tr> + <td>Coinbase</td> + <td id="coinbase"></td> + </tr> + </table> +</body> + +<script type="text/javascript"> + var web3 = require('web3'); + var eth = web3.eth; + + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + + document.querySelector("#number").innerHTML = eth.number; + document.querySelector("#coinbase").innerHTML = eth.coinbase + document.querySelector("#peer_count").innerHTML = eth.peerCount; + document.querySelector("#default_block").innerHTML = eth.defaultBlock; + document.querySelector("#accounts").innerHTML = eth.accounts; + document.querySelector("#gas_price").innerHTML = eth.gasPrice; + document.querySelector("#mining").innerHTML = eth.mining; + document.querySelector("#listening").innerHTML = eth.listening; +</script> + +</html> + diff --git a/cmd/mist/assets/examples/whisper.html b/cmd/mist/assets/examples/whisper.html new file mode 100644 index 000000000..6a7143eef --- /dev/null +++ b/cmd/mist/assets/examples/whisper.html @@ -0,0 +1,60 @@ +<!doctype> +<html> +<title>Whisper test</title> +<head> +<script type="text/javascript" src="../ext/bignumber.min.js"></script> +<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> +</head> +<body> + +<h1>Whisper test</h1> + +<button onclick="test()">Send</button> + +<table width="100%" id="table"> + <tr> + <td>Count</td> + <td id="count"></td> + </tr> + + <tr> + <td>ID</td> + <td id="id"></td> + </tr> + + <tr> + <td>Has identity</td> + <td id="known"></td> + </tr> +</table> +</body> + +<script type="text/javascript"> + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + + var shh = web3.shh; + + var id = shh.newIdentity(); + document.querySelector("#id").innerHTML = id; + document.querySelector("#known").innerHTML = shh.haveIdentity(id); + + var watch = shh.watch({topics: ["test"]}) + watch.arrived(function(message) { + document.querySelector("#table").innerHTML += "<tr><td colspan='2'>"+JSON.stringify(message)+"</td></tr>"; + }); + + function test() { + shh.post({topics: ["test"], payload: web3.fromAscii("test it")}); + count(); + + } + + function count() { + document.querySelector("#count").innerHTML = watch.messages().length; + } +</script> + +</html> + + diff --git a/cmd/mist/assets/ext/.bowerrc b/cmd/mist/assets/ext/.bowerrc new file mode 100644 index 000000000..c3a8813e8 --- /dev/null +++ b/cmd/mist/assets/ext/.bowerrc @@ -0,0 +1,5 @@ +{ + "directory": "example/js/", + "cwd": "./", + "analytics": false +}
\ No newline at end of file diff --git a/cmd/mist/assets/ext/.editorconfig b/cmd/mist/assets/ext/.editorconfig new file mode 100644 index 000000000..60a2751d3 --- /dev/null +++ b/cmd/mist/assets/ext/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false
\ No newline at end of file diff --git a/cmd/mist/assets/ext/eth.js/.gitignore b/cmd/mist/assets/ext/.gitignore index de3a847ac..399b6dc88 100644 --- a/cmd/mist/assets/ext/eth.js/.gitignore +++ b/cmd/mist/assets/ext/.gitignore @@ -4,6 +4,7 @@ # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile ~/.gitignore_global +*.swp /tmp */**/*un~ *un~ @@ -11,4 +12,7 @@ */**/.DS_Store ethereum/ethereum ethereal/ethereal - +example/js +node_modules +bower_components +npm-debug.log diff --git a/cmd/mist/assets/ext/.jshintrc b/cmd/mist/assets/ext/.jshintrc new file mode 100644 index 000000000..c0ec5f89d --- /dev/null +++ b/cmd/mist/assets/ext/.jshintrc @@ -0,0 +1,50 @@ +{ + "predef": [ + "console", + "require", + "equal", + "test", + "testBoth", + "testWithDefault", + "raises", + "deepEqual", + "start", + "stop", + "ok", + "strictEqual", + "module", + "expect", + "reject", + "impl" + ], + + "esnext": true, + "proto": true, + "node" : true, + "browser" : true, + "browserify" : true, + + "boss" : true, + "curly": false, + "debug": true, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "shadow": true, + "eqnull": true +}
\ No newline at end of file diff --git a/cmd/mist/assets/ext/.npmignore b/cmd/mist/assets/ext/.npmignore new file mode 100644 index 000000000..5bbffe4fd --- /dev/null +++ b/cmd/mist/assets/ext/.npmignore @@ -0,0 +1,9 @@ +example/js +node_modules +test +.gitignore +.editorconfig +.travis.yml +.npmignore +component.json +testling.html
\ No newline at end of file diff --git a/cmd/mist/assets/ext/.travis.yml b/cmd/mist/assets/ext/.travis.yml new file mode 100644 index 000000000..83b21d840 --- /dev/null +++ b/cmd/mist/assets/ext/.travis.yml @@ -0,0 +1,13 @@ +language: node_js +node_js: + - "0.11" + - "0.10" +before_script: + - npm install + - npm install jshint +script: + - "jshint *.js lib" +after_script: + - npm run-script build + - npm test + diff --git a/cmd/mist/assets/ext/big.js b/cmd/mist/assets/ext/big.js deleted file mode 100644 index daa8d7227..000000000 --- a/cmd/mist/assets/ext/big.js +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -var bigInt = (function () { - var base = 10000000, logBase = 7; - var sign = { - positive: false, - negative: true - }; - - var normalize = function (first, second) { - var a = first.value, b = second.value; - var length = a.length > b.length ? a.length : b.length; - for (var i = 0; i < length; i++) { - a[i] = a[i] || 0; - b[i] = b[i] || 0; - } - for (var i = length - 1; i >= 0; i--) { - if (a[i] === 0 && b[i] === 0) { - a.pop(); - b.pop(); - } else break; - } - if (!a.length) a = [0], b = [0]; - first.value = a; - second.value = b; - }; - - var parse = function (text, first) { - if (typeof text === "object") return text; - text += ""; - var s = sign.positive, value = []; - if (text[0] === "-") { - s = sign.negative; - text = text.slice(1); - } - var base = 10; - if (text.slice(0, 2) == "0x") { - base = 16; - text = text.slice(2); - } - else { - var texts = text.split("e"); - if (texts.length > 2) throw new Error("Invalid integer"); - if (texts[1]) { - var exp = texts[1]; - if (exp[0] === "+") exp = exp.slice(1); - exp = parse(exp); - if (exp.lesser(0)) throw new Error("Cannot include negative exponent part for integers"); - while (exp.notEquals(0)) { - texts[0] += "0"; - exp = exp.prev(); - } - } - text = texts[0]; - } - if (text === "-0") text = "0"; - text = text.toUpperCase(); - var isValid = (base == 16 ? /^[0-9A-F]*$/ : /^[0-9]+$/).test(text); - if (!isValid) throw new Error("Invalid integer"); - if (base == 16) { - var val = bigInt(0); - while (text.length) { - v = text.charCodeAt(0) - 48; - if (v > 9) - v -= 7; - text = text.slice(1); - val = val.times(16).plus(v); - } - return val; - } - else { - while (text.length) { - var divider = text.length > logBase ? text.length - logBase : 0; - value.push(+text.slice(divider)); - text = text.slice(0, divider); - } - var val = bigInt(value, s); - if (first) normalize(first, val); - return val; - } - }; - - var goesInto = function (a, b) { - var a = bigInt(a, sign.positive), b = bigInt(b, sign.positive); - if (a.equals(0)) throw new Error("Cannot divide by 0"); - var n = 0; - do { - var inc = 1; - var c = bigInt(a.value, sign.positive), t = c.times(10); - while (t.lesser(b)) { - c = t; - inc *= 10; - t = t.times(10); - } - while (c.lesserOrEquals(b)) { - b = b.minus(c); - n += inc; - } - } while (a.lesserOrEquals(b)); - - return { - remainder: b.value, - result: n - }; - }; - - var bigInt = function (value, s) { - var self = { - value: value, - sign: s - }; - var o = { - value: value, - sign: s, - negate: function (m) { - var first = m || self; - return bigInt(first.value, !first.sign); - }, - abs: function (m) { - var first = m || self; - return bigInt(first.value, sign.positive); - }, - add: function (n, m) { - var s, first = self, second; - if (m) (first = parse(n)) && (second = parse(m)); - else second = parse(n, first); - s = first.sign; - if (first.sign !== second.sign) { - first = bigInt(first.value, sign.positive); - second = bigInt(second.value, sign.positive); - return s === sign.positive ? - o.subtract(first, second) : - o.subtract(second, first); - } - normalize(first, second); - var a = first.value, b = second.value; - var result = [], - carry = 0; - for (var i = 0; i < a.length || carry > 0; i++) { - var sum = (a[i] || 0) + (b[i] || 0) + carry; - carry = sum >= base ? 1 : 0; - sum -= carry * base; - result.push(sum); - } - return bigInt(result, s); - }, - plus: function (n, m) { - return o.add(n, m); - }, - subtract: function (n, m) { - var first = self, second; - if (m) (first = parse(n)) && (second = parse(m)); - else second = parse(n, first); - if (first.sign !== second.sign) return o.add(first, o.negate(second)); - if (first.sign === sign.negative) return o.subtract(o.negate(second), o.negate(first)); - if (o.compare(first, second) === -1) return o.negate(o.subtract(second, first)); - var a = first.value, b = second.value; - var result = [], - borrow = 0; - for (var i = 0; i < a.length; i++) { - var tmp = a[i] - borrow; - borrow = tmp < b[i] ? 1 : 0; - var minuend = (borrow * base) + tmp - b[i]; - result.push(minuend); - } - return bigInt(result, sign.positive); - }, - minus: function (n, m) { - return o.subtract(n, m); - }, - multiply: function (n, m) { - var s, first = self, second; - if (m) (first = parse(n)) && (second = parse(m)); - else second = parse(n, first); - s = first.sign !== second.sign; - var a = first.value, b = second.value; - var resultSum = []; - for (var i = 0; i < a.length; i++) { - resultSum[i] = []; - var j = i; - while (j--) { - resultSum[i].push(0); - } - } - var carry = 0; - for (var i = 0; i < a.length; i++) { - var x = a[i]; - for (var j = 0; j < b.length || carry > 0; j++) { - var y = b[j]; - var product = y ? (x * y) + carry : carry; - carry = product > base ? Math.floor(product / base) : 0; - product -= carry * base; - resultSum[i].push(product); - } - } - var max = -1; - for (var i = 0; i < resultSum.length; i++) { - var len = resultSum[i].length; - if (len > max) max = len; - } - var result = [], carry = 0; - for (var i = 0; i < max || carry > 0; i++) { - var sum = carry; - for (var j = 0; j < resultSum.length; j++) { - sum += resultSum[j][i] || 0; - } - carry = sum > base ? Math.floor(sum / base) : 0; - sum -= carry * base; - result.push(sum); - } - return bigInt(result, s); - }, - times: function (n, m) { - return o.multiply(n, m); - }, - divmod: function (n, m) { - var s, first = self, second; - if (m) (first = parse(n)) && (second = parse(m)); - else second = parse(n, first); - s = first.sign !== second.sign; - if (bigInt(first.value, first.sign).equals(0)) return { - quotient: bigInt([0], sign.positive), - remainder: bigInt([0], sign.positive) - }; - if (second.equals(0)) throw new Error("Cannot divide by zero"); - var a = first.value, b = second.value; - var result = [], remainder = []; - for (var i = a.length - 1; i >= 0; i--) { - var n = [a[i]].concat(remainder); - var quotient = goesInto(b, n); - result.push(quotient.result); - remainder = quotient.remainder; - } - result.reverse(); - return { - quotient: bigInt(result, s), - remainder: bigInt(remainder, first.sign) - }; - }, - divide: function (n, m) { - return o.divmod(n, m).quotient; - }, - over: function (n, m) { - return o.divide(n, m); - }, - mod: function (n, m) { - return o.divmod(n, m).remainder; - }, - pow: function (n, m) { - var first = self, second; - if (m) (first = parse(n)) && (second = parse(m)); - else second = parse(n, first); - var a = first, b = second; - if (b.lesser(0)) return ZERO; - if (b.equals(0)) return ONE; - var result = bigInt(a.value, a.sign); - - if (b.mod(2).equals(0)) { - var c = result.pow(b.over(2)); - return c.times(c); - } else { - return result.times(result.pow(b.minus(1))); - } - }, - next: function (m) { - var first = m || self; - return o.add(first, 1); - }, - prev: function (m) { - var first = m || self; - return o.subtract(first, 1); - }, - compare: function (n, m) { - var first = self, second; - if (m) (first = parse(n)) && (second = parse(m, first)); - else second = parse(n, first); - normalize(first, second); - if (first.value.length === 1 && second.value.length === 1 && first.value[0] === 0 && second.value[0] === 0) return 0; - if (second.sign !== first.sign) return first.sign === sign.positive ? 1 : -1; - var multiplier = first.sign === sign.positive ? 1 : -1; - var a = first.value, b = second.value; - for (var i = a.length - 1; i >= 0; i--) { - if (a[i] > b[i]) return 1 * multiplier; - if (b[i] > a[i]) return -1 * multiplier; - } - return 0; - }, - compareAbs: function (n, m) { - var first = self, second; - if (m) (first = parse(n)) && (second = parse(m, first)); - else second = parse(n, first); - first.sign = second.sign = sign.positive; - return o.compare(first, second); - }, - equals: function (n, m) { - return o.compare(n, m) === 0; - }, - notEquals: function (n, m) { - return !o.equals(n, m); - }, - lesser: function (n, m) { - return o.compare(n, m) < 0; - }, - greater: function (n, m) { - return o.compare(n, m) > 0; - }, - greaterOrEquals: function (n, m) { - return o.compare(n, m) >= 0; - }, - lesserOrEquals: function (n, m) { - return o.compare(n, m) <= 0; - }, - isPositive: function (m) { - var first = m || self; - return first.sign === sign.positive; - }, - isNegative: function (m) { - var first = m || self; - return first.sign === sign.negative; - }, - isEven: function (m) { - var first = m || self; - return first.value[0] % 2 === 0; - }, - isOdd: function (m) { - var first = m || self; - return first.value[0] % 2 === 1; - }, - toString: function (m) { - var first = m || self; - var str = "", len = first.value.length; - while (len--) { - if (first.value[len].toString().length === 8) str += first.value[len]; - else str += (base.toString() + first.value[len]).slice(-logBase); - } - while (str[0] === "0") { - str = str.slice(1); - } - if (!str.length) str = "0"; - var s = (first.sign === sign.positive || str == "0") ? "" : "-"; - return s + str; - }, - toHex: function (m) { - var first = m || self; - var str = ""; - var l = this.abs(); - while (l > 0) { - var qr = l.divmod(256); - var b = qr.remainder.toJSNumber(); - str = (b >> 4).toString(16) + (b & 15).toString(16) + str; - l = qr.quotient; - } - return (this.isNegative() ? "-" : "") + "0x" + str; - }, - toJSNumber: function (m) { - return +o.toString(m); - }, - valueOf: function (m) { - return o.toJSNumber(m); - } - }; - return o; - }; - - var ZERO = bigInt([0], sign.positive); - var ONE = bigInt([1], sign.positive); - var MINUS_ONE = bigInt([1], sign.negative); - - var fnReturn = function (a) { - if (typeof a === "undefined") return ZERO; - return parse(a); - }; - fnReturn.zero = ZERO; - fnReturn.one = ONE; - fnReturn.minusOne = MINUS_ONE; - return fnReturn; -})(); - -if (typeof module !== "undefined") { - module.exports = bigInt; -} - diff --git a/cmd/mist/assets/ext/bignumber.min.js b/cmd/mist/assets/ext/bignumber.min.js new file mode 100644 index 000000000..c1627d780 --- /dev/null +++ b/cmd/mist/assets/ext/bignumber.min.js @@ -0,0 +1,2 @@ +/*! bignumber.js v2.0.0 https://github.com/MikeMcl/bignumber.js/LICENCE */ +(function(n){"use strict";function t(n,i){var b,a,l,p,o,w,s=this;if(!(s instanceof t))return new t(n,i);if(n instanceof t){if(i==null){u=0;s.s=n.s;s.e=n.e;s.c=(n=n.c)?n.slice():n;return}n+=""}else if(p=(o=typeof n)=="number"){if(i==null&&n===~~n){for(s.s=1/n<0?(n=-n,-1):1,a=u=0,l=n;l>=10;l/=10,a++);s.e=a;s.c=[n];return}n=n===0&&1/n<0?"-0":n+""}else o!="string"&&(n+="");if(o=n,i==null&&ft.test(o))s.s=o.charCodeAt(0)===45?(o=o.slice(1),-1):1;else{if(i==10)return s=new t(o),y(s,c+s.e+1,h);if(o=lt.call(o).replace(/^\+(?!-)/,""),s.s=o.charCodeAt(0)===45?(o=o.replace(/^-(?!-)/,""),-1):1,i!=null?i!=~~i&&d||(e=!(i>=2&&i<65))?(f(i,2),w=ft.test(o)):(b="["+ut.slice(0,i=i|0)+"]+",o=o.replace(/\.$/,"").replace(/^\./,"0."),(w=new RegExp("^"+b+"(?:\\."+b+")?$",i<37?"i":"").test(o))?(p&&(o.replace(/^0\.0*|\./,"").length>15&&f(n,0),p=!p),o=ct(o,10,i,s.s)):o!="Infinity"&&o!="NaN"&&(f(n,1,i),n="NaN")):w=ft.test(o),!w){s.c=s.e=null;o!="Infinity"&&(o!="NaN"&&f(n,3),s.s=null);u=0;return}}for((a=o.indexOf("."))>-1&&(o=o.replace(".","")),(l=o.search(/e/i))>0?(a<0&&(a=l),a+=+o.slice(l+1),o=o.substring(0,l)):a<0&&(a=o.length),l=0;o.charCodeAt(l)===48;l++);for(i=o.length;o.charCodeAt(--i)===48;);if(o=o.slice(l,i+1),o)if(i=o.length,p&&i>15&&f(n,0),a=a-l-1,a>v)s.c=s.e=null;else if(a<nt)s.c=[s.e=0];else{if(s.e=a,s.c=[],l=(a+1)%r,a<0&&(l+=r),l<i){for(l&&s.c.push(+o.slice(0,l)),i-=r;l<i;s.c.push(+o.slice(l,l+=r)));o=o.slice(l);l=r-o.length}else l-=i;for(;l--;o+="0");s.c.push(+o)}else s.c=[s.e=0];u=0}function et(n,t,i){for(var f=1,u=t.length;!t[--u];t.pop());for(u=t[0];u>=10;u/=10,f++);return(i=f+i*r-1)>v?n.c=n.e=null:i<nt?n.c=[n.e=0]:(n.e=i,n.c=t),n}function tt(n){for(var t,f,e=1,i=n.length,u=n[0]+"";e<i;){for(t=n[e++]+"",f=r-t.length;f--;t="0"+t);u+=t}for(i=u.length;u.charCodeAt(--i)===48;);return u.slice(0,i+1||1)}function ht(n,t,i){for(var u,r=[0],f,e=0,o=n.length;e<o;){for(f=r.length;f--;r[f]*=t);for(r[u=0]+=ut.indexOf(n.charAt(e++));u<r.length;u++)r[u]>i-1&&(r[u+1]==null&&(r[u+1]=0),r[u+1]+=r[u]/i|0,r[u]%=i)}return r.reverse()}function ct(n,i,r,u){var l,e,v,y,s,f,w,o=n.indexOf("."),p=h;for(r<37&&(n=n.toLowerCase()),o>=0&&(n=n.replace(".",""),w=new t(r),s=w.pow(n.length-o),w.c=ht(s.toFixed(),10,i),w.e=w.c.length),f=ht(n,r,i),e=v=f.length;f[--v]==0;f.pop());if(!f[0])return"0";if(o<0?--e:(s.c=f,s.e=e,s.s=u,s=a(s,w,c,p,i),f=s.c,y=s.r,e=s.e),l=e+c+1,o=f[l],v=i/2,y=y||l<0||f[l+1]!=null,y=p<4?(o!=null||y)&&(p==0||p==(s.s<0?3:2)):o>v||o==v&&(p==4||y||p==6&&f[l-1]&1||p==(s.s<0?8:7)),l<1||!f[0])f.length=1,v=0,y?(f[0]=1,e=-c):e=f[0]=0;else{if(f.length=l,y)for(--i;++f[--l]>i;)f[l]=0,l||(++e,f.unshift(1));for(v=f.length;!f[--v];);}for(o=0,n="";o<=v;n+=ut.charAt(f[o++]));if(e<0){for(;++e;n="0"+n);n="0."+n}else if(o=n.length,++e>o)for(e-=o;e--;n+="0");else e<o&&(n=n.slice(0,e)+"."+n.slice(e));return n}function rt(n,i,r){var o,u,e,f=(n=new t(n)).e;if(i==null?o=0:(y(n,++i,h),o=r?i:i+n.e-f,f=n.e),u=tt(n.c),r==1||r==2&&(i<=f||f<=p)){for(;u.length<o;u+="0");u.length>1&&(u=u.charAt(0)+"."+u.slice(1));u+=(f<0?"e":"e+")+f}else{if(r=u.length,f<0){for(e=o-r;++f;u="0"+u);u="0."+u}else if(++f>r){for(e=o-f,f-=r;f--;u+="0");e>0&&(u+=".")}else e=o-r,f<r?u=u.slice(0,f)+"."+u.slice(f):e>0&&(u+=".");if(e>0)for(;e--;u+="0");}return n.s<0&&n.c[0]?"-"+u:u}function f(n,t,i,r,f,o){if(d){var c,s=["new BigNumber","cmp","div","eq","gt","gte","lt","lte","minus","mod","plus","times","toFraction","divToInt"][u?u<0?-u:u:1/u<0?1:0]+"()",h=e?" out of range":" not a"+(f?" non-zero":"n")+" integer";h=([s+" number type has more than 15 significant digits",s+" not a base "+i+" number",s+" base"+h,s+" not a number"][t]||i+"() "+t+(o?" not a boolean or binary digit":h+(r?" or not ["+(e?" negative, positive":" integer, integer")+" ]":"")))+": "+n;e=u=0;c=new Error(h);c.name="BigNumber Error";throw c;}}function y(n,t,i,u){var c,o,e,s,a,h,p,f,y=st;if(f=n.c){n:{for(c=1,s=f[0];s>=10;s/=10,c++);if(o=t-c,o<0)o+=r,e=t,a=f[h=0],p=a/y[c-e-1]%10|0;else if(h=Math.ceil((o+1)/r),h>=f.length)if(u){for(;f.length<=h;f.push(0));a=p=0;c=1;o%=r;e=o-r+1}else break n;else{for(a=s=f[h],c=1;s>=10;s/=10,c++);o%=r;e=o-r+c;p=e<0?0:a/y[c-e-1]%10|0}if(u=u||t<0||f[h+1]!=null||(e<0?a:a%y[c-e-1]),u=i<4?(p||u)&&(i==0||i==(n.s<0?3:2)):p>5||p==5&&(i==4||u||i==6&&(o>0?e>0?a/y[c-e]:0:f[h-1])%10&1||i==(n.s<0?8:7)),t<1||!f[0])return f.length=0,u?(t-=n.e+1,f[0]=y[t%r],n.e=-t||0):f[0]=n.e=0,n;if(o==0?(f.length=h,s=1,h--):(f.length=h+1,s=y[r-o],f[h]=e>0?g(a/y[c-e]%y[e])*s:0),u)for(;;)if(h==0){for(o=1,e=f[0];e>=10;e/=10,o++);for(e=f[0]+=s,s=1;e>=10;e/=10,s++);o!=s&&(n.e++,f[0]==l&&(f[0]=1));break}else{if(f[h]+=s,f[h]!=l)break;f[h--]=0;s=1}for(o=f.length;f[--o]===0;f.pop());}n.e>v?n.c=n.e=null:n.e<nt&&(n.c=[n.e=0])}return n}var o=1e9,ot=1e6,c=20,h=4,p=-7,k=21,nt=-o,v=o,d=!0,w=parseInt,b={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:"Â ",fractionGroupSize:0},i=t.prototype,ut="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",e,u=0,g=Math.floor,ft=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,lt=String.prototype.trim||function(){return this.replace(/^\s+|\s+$/g,"")},l=1e14,r=14,s=1e7,st=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],it=new t(1),a;t.ROUND_UP=0;t.ROUND_DOWN=1;t.ROUND_CEIL=2;t.ROUND_FLOOR=3;t.ROUND_HALF_UP=4;t.ROUND_HALF_DOWN=5;t.ROUND_HALF_EVEN=6;t.ROUND_HALF_CEIL=7;t.ROUND_HALF_FLOOR=8;t.config=function(){var n,t,g=0,i={},y=arguments,a=y[0],s="config",r=function(n,t,i){return!((e=n<t||n>i)||w(n)!=n&&n!==0)},l=a&&typeof a=="object"?function(){if(a.hasOwnProperty(t))return(n=a[t])!=null}:function(){if(y.length>g)return(n=y[g++])!=null};if(l(t="DECIMAL_PLACES")&&(r(n,0,o)?c=n|0:f(n,t,s)),i[t]=c,l(t="ROUNDING_MODE")&&(r(n,0,8)?h=n|0:f(n,t,s)),i[t]=h,l(t="EXPONENTIAL_AT")&&(r(n,-o,o)?p=-(k=~~(n<0?-n:+n)):!e&&n&&r(n[0],-o,0)&&r(n[1],0,o)?(p=~~n[0],k=~~n[1]):f(n,t,s,1)),i[t]=[p,k],l(t="RANGE")&&(r(n,-o,o)&&~~n?nt=-(v=~~(n<0?-n:+n)):!e&&n&&r(n[0],-o,-1)&&r(n[1],1,o)?(nt=~~n[0],v=~~n[1]):f(n,t,s,1,1)),i[t]=[nt,v],l(t="ERRORS")&&(n===!!n||n===1||n===0?(e=u=0,w=(d=!!n)?parseInt:parseFloat):f(n,t,s,0,0,1)),i[t]=d,l(t="FORMAT"))if(typeof n=="object")b=n;else if(d){i=new Error(s+"() "+t+" not an object: "+n);i.name="BigNumber Error";throw i;}return i[t]=b,i};a=function(){function n(n,t,i){var f,e,o,h,r=0,u=n.length,c=t%s,l=t/s|0;for(n=n.slice();u--;)o=n[u]%s,h=n[u]/s|0,f=l*o+h*c,e=c*o+f%s*s+r,r=(e/i|0)+(f/s|0)+l*h,n[u]=e%i;return r&&n.unshift(r),n}function i(n,t,i,r){var u,f;if(i!=r)f=i>r?1:-1;else for(u=f=0;u<i;u++)if(n[u]!=t[u]){f=n[u]>t[u]?1:-1;break}return f}function u(n,t,i,r){for(var u=0;i--;)n[i]-=u,u=n[i]<t[i]?1:0,n[i]=u*r+n[i]-t[i];for(;!n[0]&&n.length>1;n.shift());}return function(f,e,o,s,h){var nt,ut,a,ot,p,tt,ft,it,et,v,w,st,ht,rt,lt,k,ct,d=f.s==e.s?1:-1,b=f.c,c=e.c;if(!b||!b[0]||!c||!c[0])return new t(!f.s||!e.s||(b?c&&b[0]==c[0]:!c)?NaN:b&&b[0]==0||!c?d*0:d/0);for(it=new t(d),et=it.c=[],ut=f.e-e.e,d=o+ut+1,h||(h=l,ut=(rt=f.e/r,a=rt|0,rt>0||rt===a?a:a-1)-(k=e.e/r,a=k|0,k>0||k===a?a:a-1),d=d/r|0),a=0;c[a]==(b[a]||0);a++);if(c[a]>(b[a]||0)&&ut--,d<0)et.push(1),ot=!0;else{for(rt=b.length,k=c.length,a=0,d+=2,p=g(h/(c[0]+1)),p>1&&(c=n(c,p,h),b=n(b,p,h),k=c.length,rt=b.length),ht=k,v=b.slice(0,k),w=v.length;w<k;v[w++]=0);ct=c.slice();ct.unshift(0);lt=c[0];c[1]>=h/2&<++;do p=0,nt=i(c,v,k,w),nt<0?(st=v[0],k!=w&&(st=st*h+(v[1]||0)),p=g(st/lt),p>1?(p>=h&&(p=h-1),tt=n(c,p,h),ft=tt.length,w=v.length,nt=i(tt,v,ft,w),nt==1&&(p--,u(tt,k<ft?ct:c,ft,h))):(p==0&&(nt=p=1),tt=c.slice()),ft=tt.length,ft<w&&tt.unshift(0),u(v,tt,w,h),nt==-1&&(w=v.length,nt=i(c,v,k,w),nt<1&&(p++,u(v,k<w?ct:c,w,h))),w=v.length):nt===0&&(p++,v=[0]),et[a++]=p,nt&&v[0]?v[w++]=b[ht]||0:(v=[b[ht]],w=1);while((ht++<rt||v[0]!=null)&&d--);ot=v[0]!=null;et[0]||et.shift()}if(h==l){for(a=1,d=et[0];d>=10;d/=10,a++);y(it,o+(it.e=a+ut*r-1)+1,s,ot)}else it.e=ut,it.r=+ot;return it}}();i.absoluteValue=i.abs=function(){var n=new t(this);return n.s<0&&(n.s=1),n};i.ceil=function(){return y(new t(this),this.e+1,2)};i.comparedTo=i.cmp=function(n,i){var f,l=this,e=l.c,o=(u=-u,n=new t(n,i)).c,r=l.s,c=n.s,s=l.e,h=n.e;if(!r||!c)return null;if(f=e&&!e[0],i=o&&!o[0],f||i)return f?i?0:-c:r;if(r!=c)return r;if(f=r<0,i=s==h,!e||!o)return i?0:!e^f?1:-1;if(!i)return s>h^f?1:-1;for(r=-1,c=(s=e.length)<(h=o.length)?s:h;++r<c;)if(e[r]!=o[r])return e[r]>o[r]^f?1:-1;return s==h?0:s>h^f?1:-1};i.decimalPlaces=i.dp=function(){var n,t,i=this.c;if(!i)return null;if(n=((t=i.length-1)-g(this.e/r))*r,t=i[t])for(;t%10==0;t/=10,n--);return n<0&&(n=0),n};i.dividedBy=i.div=function(n,i){return u=2,a(this,new t(n,i),c,h)};i.dividedToIntegerBy=i.divToInt=function(n,i){return u=13,a(this,new t(n,i),0,1)};i.equals=i.eq=function(n,t){return u=3,this.cmp(n,t)===0};i.floor=function(){return y(new t(this),this.e+1,3)};i.greaterThan=i.gt=function(n,t){return u=4,this.cmp(n,t)>0};i.greaterThanOrEqualTo=i.gte=function(n,t){return u=5,(t=this.cmp(n,t))==1||t===0};i.isFinite=function(){return!!this.c};i.isInteger=i.isInt=function(){return!!this.c&&g(this.e/r)>this.c.length-2};i.isNaN=function(){return!this.s};i.isNegative=i.isNeg=function(){return this.s<0};i.isZero=function(){return!!this.c&&this.c[0]==0};i.lessThan=i.lt=function(n,t){return u=6,this.cmp(n,t)<0};i.lessThanOrEqualTo=i.lte=function(n,t){return u=7,(t=this.cmp(n,t))==-1||t===0};i.minus=function(n,i){var e,c,v,w,p=this,s=p.s;if(u=8,n=new t(n,i),i=n.s,!s||!i)return new t(NaN);if(s!=i)return n.s=-i,p.plus(n);var y=p.e/r,a=n.e/r,f=p.c,o=n.c;if(!y||!a){if(!f||!o)return f?(n.s=-i,n):new t(o?p:NaN);if(!f[0]||!o[0])return o[0]?(n.s=-i,n):new t(f[0]?p:h==3?-0:0)}if(e=y|0,y=y>0||y===e?e:e-1,e=a|0,a=a>0||a===e?e:e-1,f=f.slice(),s=y-a){for((w=s<0)?(s=-s,v=f):(a=y,v=o),v.reverse(),i=s;i--;v.push(0));v.reverse()}else for(c=(w=(s=f.length)<(i=o.length))?s:i,s=i=0;i<c;i++)if(f[i]!=o[i]){w=f[i]<o[i];break}if(w&&(v=f,f=o,o=v,n.s=-n.s),i=(c=o.length)-(e=f.length),i>0)for(;i--;f[e++]=0);for(i=l-1;c>s;){if(f[--c]<o[c]){for(e=c;e&&!f[--e];f[e]=i);--f[e];f[c]+=l}f[c]-=o[c]}for(;f[0]==0;f.shift(),--a);return f[0]?et(n,f,a):(n.s=h==3?-1:1,n.c=[n.e=0],n)};i.modulo=i.mod=function(n,i){u=9;var r=this,f=r.c,e=(n=new t(n,i)).c,o=r.s,s=n.s;return(i=!o||!s||e&&!e[0],i||f&&!f[0])?new t(i?NaN:r):(r.s=n.s=1,i=n.cmp(r)==1,r.s=o,n.s=s,i?new t(r):r.minus(a(r,n,0,1).times(n)))};i.negated=i.neg=function(){var n=new t(this);return n.s=-n.s||null,n};i.plus=function(n,i){var h,a=this,f=a.s;if(u=10,n=new t(n,i),i=n.s,!f||!i)return new t(NaN);if(f!=i)return n.s=-i,a.minus(n);var c=a.e/r,o=n.e/r,e=a.c,s=n.c;if(!c||!o){if(!e||!s)return new t(f/0);if(!e[0]||!s[0])return s[0]?n:new t(e[0]?a:f*0)}if(f=c|0,c=c>0||c===f?f:f-1,f=o|0,o=o>0||o===f?f:f-1,e=e.slice(),f=c-o){for(f>0?(o=c,h=s):(f=-f,h=e),h.reverse();f--;h.push(0));h.reverse()}for(f=e.length,i=s.length,f-i<0&&(h=s,s=e,e=h,i=f),f=0;i;)f=(e[--i]=e[i]+s[i]+f)/l|0,e[i]%=l;return f&&(e.unshift(f),++o),et(n,e,o)};i.round=function(n,i){return n=n==null||((e=n<0||n>o)||w(n)!=n)&&!f(n,"decimal places","round")?0:n|0,i=i==null||((e=i<0||i>8)||w(i)!=i&&i!==0)&&!f(i,"mode","round")?h:i|0,y(new t(this),n+this.e+1,i)};i.squareRoot=i.sqrt=function(){var v,i,r,s,f,e=this,o=e.c,n=e.s,u=e.e,l=c+4,p=new t("0.5");if(n!==1||!o||!o[0])return new t(!n||n<0&&(!o||o[0])?NaN:o?e:1/0);if(n=Math.sqrt(+e),n==0||n==1/0?(i=tt(o),(i.length+u)%2==0&&(i+="0"),n=Math.sqrt(i),u=g((u+1)/2)-(u<0||u%2),n==1/0?i="1e"+u:(i=n.toExponential(),i=i.slice(0,i.indexOf("e")+1)+u),r=new t(i)):r=new t(n.toString()),r.c[0])for(u=r.e,n=u+l,n<3&&(n=0);;)if(f=r,r=p.times(f.plus(a(e,f,l,1))),tt(f.c).slice(0,n)===(i=tt(r.c)).slice(0,n))if(r.e<u&&--n,i=i.slice(n-3,n+1),i!="9999"&&(s||i!="4999")){+i&&(+i.slice(1)||i.charAt(0)!="5")||(y(r,r.e+c+2,1),v=!r.times(r).eq(e));break}else{if(!s&&(y(f,f.e+c+2,0),f.times(f).eq(e))){r=f;break}l+=4;n+=4;s=1}return y(r,r.e+c+1,h,v)};i.times=function(n,i){var p,e,w,b,a,y,k,d,g,nt=this,o=nt.c,h=(u=11,n=new t(n,i)).c,c=nt.e/r,f=n.e/r,v=nt.s;if(n.s=v==(i=n.s)?1:-1,!c&&(!o||!o[0])||!f&&(!h||!h[0]))return new t(!v||!i||o&&!o[0]&&!h||h&&!h[0]&&!o?NaN:!o||!h?n.s/0:n.s*0);for(e=(e=c|0,c>0||c===e?e:e-1)+(e=f|0,f>0||f===e?e:e-1),v=o.length,i=h.length,v<i&&(a=o,o=h,h=a,f=v,v=i,i=f),f=v+i,a=[];f--;a.push(0));for(c=i;--c>=0;){for(p=0,f=v+c,w=v,d=h[c]%s,g=h[c]/s|0;f>c;)y=o[--w]%s,k=o[w]/s|0,b=g*y+k*d,y=d*y+b%s*s+a[f]+p,p=(y/l|0)+(b/s|0)+g*k,a[f--]=y%l;a[f]=p}return p?++e:a.shift(),et(n,a,e)};i.toExponential=function(n){var t=this;return t.c?rt(t,n==null||((e=n<0||n>o)||w(n)!=n&&n!==0)&&!f(n,"decimal places","toExponential")?null:n|0,1):t.toString()};i.toFixed=function(n){var t,i=this,r=p,u=k;return n=n==null||((e=n<0||n>o)||w(n)!=n&&n!==0)&&!f(n,"decimal places","toFixed")?null:i.e+(n|0),p=-(k=1/0),n!=null&&i.c?(t=rt(i,n),i.s<0&&i.c&&(i.c[0]?t.indexOf("-")<0&&(t="-"+t):t=t.replace("-",""))):t=i.toString(),p=r,k=u,t};i.toFormat=function(n){var f=this;if(!f.c)return f.toString();var t,h=f.s<0,c=b.groupSeparator,r=+b.groupSize,u=+b.secondaryGroupSize,l=f.toFixed(n).split("."),i=l[0],s=l[1],e=h?i.slice(1):i,o=e.length;if(u&&(t=r,r=u,u=t,o-=t),r>0&&o>0){for(t=o%r||r,i=e.substr(0,t);t<o;t+=r)i+=c+e.substr(t,r);u>0&&(i+=c+e.slice(t));h&&(i="-"+i)}return s?i+b.decimalSeparator+((u=+b.fractionGroupSize)?s.replace(new RegExp("\\d{"+u+"}\\B","g"),"$&"+b.fractionGroupSeparator):s):i};i.toFraction=function(n){var ut,c,i,w,k,o,s,nt,rt,l=c=new t(it),y=s=new t(it),b=this,ft=b.c,p=new t(it);if(!ft)return b.toString();for(rt=tt(ft),w=p.e=rt.length-b.e-1,p.c[0]=st[(k=w%r)<0?r+k:k],(n==null||(!(u=12,o=new t(n)).s||(e=o.cmp(l)<0||!o.c)||d&&g(o.e/r)<o.c.length-1)&&!f(n,"max denominator","toFraction")||(n=o).cmp(p)>0)&&(n=w>0?p:l),k=v,v=1/0,o=new t(rt),s.c[0]=0;;){if(nt=a(o,p,0,1),i=c.plus(nt.times(y)),i.cmp(n)==1)break;c=y;y=i;l=s.plus(nt.times(i=l));s=i;p=o.minus(nt.times(i=p));o=i}return i=a(n.minus(c),y,0,1),s=s.plus(i.times(l)),c=c.plus(i.times(y)),s.s=l.s=b.s,w*=2,ut=a(l,y,w,h).minus(b).abs().cmp(a(s,c,w,h).minus(b).abs())<1?[l.toString(),y.toString()]:[s.toString(),c.toString()],v=k,ut};i.toNumber=function(){var n=this;return+n||(n.s?0*n.s:NaN)};i.toPower=i.pow=function(n){var i=n*0==0?~~n:n,r=new t(this),u=new t(it);if(((e=n<-ot||n>ot)&&(i=n/0)||w(n)!=n&&n!==0&&!(i=NaN))&&!f(n,"exponent","pow")||!i)return new t(Math.pow(+r,i));for(i=i<0?-i:i;;){if(i&1&&(u=u.times(r)),i>>=1,!i)break;r=r.times(r)}return n<0?it.div(u):u};i.toPrecision=function(n){var t=this;return n==null||((e=n<1||n>o)||w(n)!=n)&&!f(n,"precision","toPrecision")||!t.c?t.toString():rt(t,--n|0,2)};i.toString=function(n){var r,t,o,u=this,i=u.e;if(i===null)t=u.s?"Infinity":"NaN";else{if(n==r&&(i<=p||i>=k))return rt(u,r,1);if(t=tt(u.c),i<0){for(;++i;t="0"+t);t="0."+t}else if(o=t.length,i>0)if(++i>o)for(i-=o;i--;t+="0");else i<o&&(t=t.slice(0,i)+"."+t.slice(i));else if(r=t.charAt(0),o>1)t=r+"."+t.slice(1);else if(r=="0")return r;if(n!=null)if((e=!(n>=2&&n<65))||n!=~~n&&d)f(n,"base","toS");else if(t=ct(t,n|0,10,u.s),t=="0")return t}return u.s<0?"-"+t:t};i.valueOf=i.toJSON=function(){return this.toString()};typeof module!="undefined"&&module.exports?module.exports=t:typeof define=="function"&&define.amd?define(function(){return t}):n.BigNumber=t})(this)
\ No newline at end of file diff --git a/cmd/mist/assets/ext/eth.js/README.md b/cmd/mist/assets/ext/eth.js/README.md deleted file mode 100644 index 86e2969be..000000000 --- a/cmd/mist/assets/ext/eth.js/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Ethereum JavaScript API - -This is the Ethereum compatible JavaScript API using `Promise`s -which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. - -For an example see `index.html`. - -**Please note this repo is in it's early stage.** - -If you'd like to run a WebSocket ethereum node check out -[go-ethereum](https://github.com/ethereum/go-ethereum). - -To install ethereum and spawn a node: - -``` -go get github.com/ethereum/go-ethereum/ethereum -ethereum -ws -loglevel=4 -``` diff --git a/cmd/mist/assets/ext/eth.js/httprpc.js b/cmd/mist/assets/ext/eth.js/httprpc.js deleted file mode 100644 index 085b4693d..000000000 --- a/cmd/mist/assets/ext/eth.js/httprpc.js +++ /dev/null @@ -1,70 +0,0 @@ -(function () { - var HttpRpcProvider = function (host) { - this.handlers = []; - this.host = host; - }; - - function formatJsonRpcObject(object) { - return { - jsonrpc: '2.0', - method: object.call, - params: object.args, - id: object._id - } - }; - - function formatJsonRpcMessage(message) { - var object = JSON.parse(message); - - return { - _id: object.id, - data: object.result - }; - }; - - HttpRpcProvider.prototype.sendRequest = function (payload, cb) { - var data = formatJsonRpcObject(payload); - - var request = new XMLHttpRequest(); - request.open("POST", this.host, true); - request.send(JSON.stringify(data)); - request.onreadystatechange = function () { - if (request.readyState === 4 && cb) { - cb(request); - } - } - }; - - HttpRpcProvider.prototype.send = function (payload) { - var self = this; - this.sendRequest(payload, function (request) { - self.handlers.forEach(function (handler) { - handler.call(self, formatJsonRpcMessage(request.responseText)); - }); - }); - }; - - HttpRpcProvider.prototype.poll = function (payload, id) { - var self = this; - this.sendRequest(payload, function (request) { - var parsed = JSON.parse(request.responseText); - if (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result) { - return; - } - self.handlers.forEach(function (handler) { - handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); - }); - }); - }; - - Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { - set: function (handler) { - this.handlers.push(handler); - } - }); - - if (typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.HttpRpcProvider = HttpRpcProvider; - } -})(); - diff --git a/cmd/mist/assets/ext/eth.js/index.html b/cmd/mist/assets/ext/eth.js/index.html deleted file mode 100644 index 2b3f50a14..000000000 --- a/cmd/mist/assets/ext/eth.js/index.html +++ /dev/null @@ -1,33 +0,0 @@ -<!doctype> -<html> - -<head> -<script type="text/javascript" src="main.js"></script> -<script type="text/javascript" src="websocket.js"></script> -<script type="text/javascript" src="qt.js"></script> -<script type="text/javascript" src="httprpc.js"></script> -<script type="text/javascript"> -function registerName() { - var name = document.querySelector("#name").value; - name = web3.fromAscii(name); - - var eth = web3.eth; - eth.transact({to: "NameReg", gas: "10000", gasPrice: eth.gasPrice, data: [web3.fromAscii("register"), name]}).then(function(tx) { - document.querySelector("#result").innerHTML = "Registered name. Please wait for the next block to come through."; - }, function(err) { - console.log(err); - }); -} -</script> -</head> - -<body> - -<h1>std::name_reg</h1> -<input type="text" id="name"></input> -<input type="submit" onClick="registerName();"></input> -<div id="result"></div> - -</body> - -</html> diff --git a/cmd/mist/assets/ext/eth.js/main.js b/cmd/mist/assets/ext/eth.js/main.js deleted file mode 100644 index 5c7ca0603..000000000 --- a/cmd/mist/assets/ext/eth.js/main.js +++ /dev/null @@ -1,432 +0,0 @@ -(function(window) { - function isPromise(o) { - return o instanceof Promise - } - - function flattenPromise (obj) { - if (obj instanceof Promise) { - return Promise.resolve(obj); - } - - if (obj instanceof Array) { - return new Promise(function (resolve) { - var promises = obj.map(function (o) { - return flattenPromise(o); - }); - - return Promise.all(promises).then(function (res) { - for (var i = 0; i < obj.length; i++) { - obj[i] = res[i]; - } - resolve(obj); - }); - }); - } - - if (obj instanceof Object) { - return new Promise(function (resolve) { - var keys = Object.keys(obj); - var promises = keys.map(function (key) { - return flattenPromise(obj[key]); - }); - - return Promise.all(promises).then(function (res) { - for (var i = 0; i < keys.length; i++) { - obj[keys[i]] = res[i]; - } - resolve(obj); - }); - }); - } - - return Promise.resolve(obj); - }; - - var ethMethods = function () { - var blockCall = function (args) { - return typeof args[0] === "string" ? "blockByHash" : "blockByNumber"; - }; - - var transactionCall = function (args) { - return typeof args[0] === "string" ? 'transactionByHash' : 'transactionByNumber'; - }; - - var uncleCall = function (args) { - return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber'; - }; - - var methods = [ - { name: 'balanceAt', call: 'balanceAt' }, - { name: 'stateAt', call: 'stateAt' }, - { name: 'countAt', call: 'countAt'}, - { name: 'codeAt', call: 'codeAt' }, - { name: 'transact', call: 'transact' }, - { name: 'call', call: 'call' }, - { name: 'block', call: blockCall }, - { name: 'transaction', call: transactionCall }, - { name: 'uncle', call: uncleCall }, - { name: 'compile', call: 'compile' } - ]; - return methods; - }; - - var ethProperties = function () { - return [ - { name: 'coinbase', getter: 'coinbase', setter: 'setCoinbase' }, - { name: 'listening', getter: 'listening', setter: 'setListening' }, - { name: 'mining', getter: 'mining', setter: 'setMining' }, - { name: 'gasPrice', getter: 'gasPrice' }, - { name: 'account', getter: 'account' }, - { name: 'accounts', getter: 'accounts' }, - { name: 'peerCount', getter: 'peerCount' }, - { name: 'defaultBlock', getter: 'defaultBlock', setter: 'setDefaultBlock' }, - { name: 'number', getter: 'number'} - ]; - }; - - var dbMethods = function () { - return [ - { name: 'put', call: 'put' }, - { name: 'get', call: 'get' }, - { name: 'putString', call: 'putString' }, - { name: 'getString', call: 'getString' } - ]; - }; - - var shhMethods = function () { - return [ - { name: 'post', call: 'post' }, - { name: 'newIdentity', call: 'newIdentity' }, - { name: 'haveIdentity', call: 'haveIdentity' }, - { name: 'newGroup', call: 'newGroup' }, - { name: 'addToGroup', call: 'addToGroup' } - ]; - }; - - var ethWatchMethods = function () { - var newFilter = function (args) { - return typeof args[0] === 'string' ? 'newFilterString' : 'newFilter'; - }; - - return [ - { name: 'newFilter', call: newFilter }, - { name: 'uninstallFilter', call: 'uninstallFilter' }, - { name: 'getMessages', call: 'getMessages' } - ]; - }; - - var shhWatchMethods = function () { - return [ - { name: 'newFilter', call: 'shhNewFilter' }, - { name: 'uninstallFilter', call: 'shhUninstallFilter' }, - { name: 'getMessage', call: 'shhGetMessages' } - ]; - }; - - var setupMethods = function (obj, methods) { - methods.forEach(function (method) { - obj[method.name] = function () { - return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { - var call = typeof method.call === "function" ? method.call(args) : method.call; - return {call: call, args: args}; - }).then(function (request) { - return new Promise(function (resolve, reject) { - web3.provider.send(request, function (result) { - //if (result || typeof result === "boolean") { - resolve(result); - return; - //} - //reject(result); - }); - }); - }).catch(function( err) { - console.error(err); - }); - }; - }); - }; - - var setupProperties = function (obj, properties) { - properties.forEach(function (property) { - var proto = {}; - proto.get = function () { - return new Promise(function(resolve, reject) { - web3.provider.send({call: property.getter}, function(result) { - resolve(result); - }); - }); - }; - if (property.setter) { - proto.set = function (val) { - return flattenPromise([val]).then(function (args) { - return new Promise(function (resolve) { - web3.provider.send({call: property.setter, args: args}, function (result) { - resolve(result); - }); - }); - }).catch(function (err) { - console.error(err); - }); - } - } - Object.defineProperty(obj, property.name, proto); - }); - }; - - var web3 = { - _callbacks: {}, - _events: {}, - providers: {}, - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, - - toAscii: function(hex) { - // Find termination - var str = ""; - var i = 0, l = hex.length; - for(; i < l; i+=2) { - var code = hex.charCodeAt(i) - if(code == 0) { - break; - } - - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - - return str; - }, - - toDecimal: function (val) { - return parseInt(val, 16); - }, - - fromAscii: function(str, pad) { - pad = pad === undefined ? 32 : pad; - var hex = this.toHex(str); - while(hex.length < pad*2) - hex += "00"; - return hex - }, - - eth: { - prototype: Object(), - watch: function (params) { - return new Filter(params, ethWatch); - }, - }, - - db: { - prototype: Object() - }, - - shh: { - prototype: Object(), - watch: function (params) { - return new Filter(params, shhWatch); - } - }, - - on: function(event, id, cb) { - if(web3._events[event] === undefined) { - web3._events[event] = {}; - } - - web3._events[event][id] = cb; - return this - }, - - off: function(event, id) { - if(web3._events[event] !== undefined) { - delete web3._events[event][id]; - } - - return this - }, - - trigger: function(event, id, data) { - var callbacks = web3._events[event]; - if (!callbacks || !callbacks[id]) { - return; - } - var cb = callbacks[id]; - cb(data); - }, - }; - - var eth = web3.eth; - setupMethods(eth, ethMethods()); - setupProperties(eth, ethProperties()); - setupMethods(web3.db, dbMethods()); - setupMethods(web3.shh, shhMethods()); - - var ethWatch = { - changed: 'changed' - }; - setupMethods(ethWatch, ethWatchMethods()); - var shhWatch = { - changed: 'shhChanged' - }; - setupMethods(shhWatch, shhWatchMethods()); - - var ProviderManager = function() { - this.queued = []; - this.polls = []; - this.ready = false; - this.provider = undefined; - this.id = 1; - - var self = this; - var poll = function () { - if (self.provider && self.provider.poll) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - self.provider.poll(data.data, data.id); - }); - } - setTimeout(poll, 12000); - }; - poll(); - }; - - ProviderManager.prototype.send = function(data, cb) { - data._id = this.id; - if (cb) { - web3._callbacks[data._id] = cb; - } - - data.args = data.args || []; - this.id++; - - if(this.provider !== undefined) { - this.provider.send(data); - } else { - console.warn("provider is not set"); - this.queued.push(data); - } - }; - - ProviderManager.prototype.set = function(provider) { - if(this.provider !== undefined && this.provider.unload !== undefined) { - this.provider.unload(); - } - - this.provider = provider; - this.ready = true; - }; - - ProviderManager.prototype.sendQueued = function() { - for(var i = 0; this.queued.length; i++) { - // Resend - this.send(this.queued[i]); - } - }; - - ProviderManager.prototype.installed = function() { - return this.provider !== undefined; - }; - - ProviderManager.prototype.startPolling = function (data, pollId) { - if (!this.provider || !this.provider.poll) { - return; - } - this.polls.push({data: data, id: pollId}); - }; - - ProviderManager.prototype.stopPolling = function (pollId) { - for (var i = this.polls.length; i--;) { - var poll = this.polls[i]; - if (poll.id === pollId) { - this.polls.splice(i, 1); - } - } - }; - - web3.provider = new ProviderManager(); - - web3.setProvider = function(provider) { - provider.onmessage = messageHandler; - web3.provider.set(provider); - web3.provider.sendQueued(); - }; - - var Filter = function(options, impl) { - this.impl = impl; - this.callbacks = []; - - var self = this; - this.promise = impl.newFilter(options); - this.promise.then(function (id) { - self.id = id; - web3.on(impl.changed, id, self.trigger.bind(self)); - web3.provider.startPolling({call: impl.changed, args: [id]}, id); - }); - }; - - Filter.prototype.arrived = function(callback) { - this.changed(callback); - } - - Filter.prototype.changed = function(callback) { - var self = this; - this.promise.then(function(id) { - self.callbacks.push(callback); - }); - }; - - Filter.prototype.trigger = function(messages) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } - }; - - Filter.prototype.uninstall = function() { - var self = this; - this.promise.then(function (id) { - self.impl.uninstallFilter(id); - web3.provider.stopPolling(id); - web3.off(impl.changed, id); - }); - }; - - Filter.prototype.messages = function() { - var self = this; - return this.promise.then(function (id) { - return self.impl.getMessages(id); - }); - }; - - function messageHandler(data) { - if(data._event !== undefined) { - web3.trigger(data._event, data._id, data.data); - return; - } - - if(data._id) { - var cb = web3._callbacks[data._id]; - if (cb) { - cb.call(this, data.data) - delete web3._callbacks[data._id]; - } - } - } - - /* - // Install default provider - if(!web3.provider.installed()) { - var sock = new web3.WebSocket("ws://localhost:40404/eth"); - - web3.setProvider(sock); - } - */ - - window.web3 = web3; - -})(this); diff --git a/cmd/mist/assets/ext/eth.js/qt.js b/cmd/mist/assets/ext/eth.js/qt.js deleted file mode 100644 index 644c37737..000000000 --- a/cmd/mist/assets/ext/eth.js/qt.js +++ /dev/null @@ -1,27 +0,0 @@ -(function() { - var QtProvider = function() { - this.handlers = []; - - var self = this; - navigator.qt.onmessage = function (message) { - self.handlers.forEach(function (handler) { - handler.call(self, JSON.parse(message.data)); - }); - } - }; - - QtProvider.prototype.send = function(payload) { - navigator.qt.postMessage(JSON.stringify(payload)); - }; - - Object.defineProperty(QtProvider.prototype, "onmessage", { - set: function(handler) { - this.handlers.push(handler); - }, - }); - - if(typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.QtProvider = QtProvider; - } -})(); - diff --git a/cmd/mist/assets/ext/eth.js/websocket.js b/cmd/mist/assets/ext/eth.js/websocket.js deleted file mode 100644 index 732a086f2..000000000 --- a/cmd/mist/assets/ext/eth.js/websocket.js +++ /dev/null @@ -1,51 +0,0 @@ -(function() { - var WebSocketProvider = function(host) { - // onmessage handlers - this.handlers = []; - // queue will be filled with messages if send is invoked before the ws is ready - this.queued = []; - this.ready = false; - - this.ws = new WebSocket(host); - - var self = this; - this.ws.onmessage = function(event) { - for(var i = 0; i < self.handlers.length; i++) { - self.handlers[i].call(self, JSON.parse(event.data), event) - } - }; - - this.ws.onopen = function() { - self.ready = true; - - for(var i = 0; i < self.queued.length; i++) { - // Resend - self.send(self.queued[i]); - } - }; - }; - WebSocketProvider.prototype.send = function(payload) { - if(this.ready) { - var data = JSON.stringify(payload); - - this.ws.send(data); - } else { - this.queued.push(payload); - } - }; - - WebSocketProvider.prototype.onMessage = function(handler) { - this.handlers.push(handler); - }; - - WebSocketProvider.prototype.unload = function() { - this.ws.close(); - }; - Object.defineProperty(WebSocketProvider.prototype, "onmessage", { - set: function(provider) { this.onMessage(provider); } - }); - - if(typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.WebSocketProvider = WebSocketProvider; - } -})(); diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js deleted file mode 100644 index aeb79e488..000000000 --- a/cmd/mist/assets/ext/ethereum.js +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -// Main Ethereum library -window.eth = { - prototype: Object(), - _callbacks: {}, - _onCallbacks: {}, - - test: function() { - var t = undefined; - postData({call: "test"}) - navigator.qt.onmessage = function(d) {console.log("onmessage called"); t = d; } - for(;;) { - if(t !== undefined) { - return t - } - } - }, - - mutan: function(code, cb) { - postData({call: "mutan", args: [code]}, cb) - }, - - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, - - toAscii: function(hex) { - // Find termination - var str = ""; - var i = 0, l = hex.length; - for(; i < l; i+=2) { - var code = hex.charCodeAt(i) - if(code == 0) { - break; - } - - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - - return str; - }, - - fromAscii: function(str, pad) { - if(pad === undefined) { - pad = 32 - } - - var hex = this.toHex(str); - - while(hex.length < pad*2) - hex += "00"; - - return hex - }, - - - // Retrieve block - // - // Either supply a number or a string. Type is determent for the lookup method - // string - Retrieves the block by looking up the hash - // number - Retrieves the block by looking up the block number - getBlock: function(numberOrHash, cb) { - var func; - if(typeof numberOrHash == "string") { - func = "getBlockByHash"; - } else { - func = "getBlockByNumber"; - } - postData({call: func, args: [numberOrHash]}, cb); - }, - - // Create transaction - // - // Transact between two state objects - transact: function(params, cb) { - if(params === undefined) { - params = {}; - } - - if(params.endowment !== undefined) - params.value = params.endowment; - if(params.code !== undefined) - params.data = params.code; - - // Make sure everything is string - var fields = ["to", "from", "value", "gas", "gasPrice"]; - for(var i = 0; i < fields.length; i++) { - if(params[fields[i]] === undefined) { - params[fields[i]] = ""; - } - params[fields[i]] = params[fields[i]].toString(); - } - - var data; - if(typeof params.data === "object") { - data = ""; - for(var i = 0; i < params.data.length; i++) { - data += params.data[i] - } - } else { - data = params.data; - } - - postData({call: "transact", args: [params.from, params.to, params.value, params.gas, params.gasPrice, "0x"+data]}, cb); - }, - - getMessages: function(filter, cb) { - postData({call: "messages", args: [filter]}, cb); - }, - - getStorageAt: function(address, storageAddress, cb) { - postData({call: "getStorage", args: [address, storageAddress]}, cb); - }, - - getEachStorageAt: function(address, cb){ - postData({call: "getEachStorage", args: [address]}, cb); - }, - - getKey: function(cb) { - postData({call: "getKey"}, cb); - }, - - getTxCountAt: function(address, cb) { - postData({call: "getTxCountAt", args: [address]}, cb); - }, - getIsMining: function(cb){ - postData({call: "getIsMining"}, cb) - }, - getIsListening: function(cb){ - postData({call: "getIsListening"}, cb) - }, - getCoinBase: function(cb){ - postData({call: "getCoinBase"}, cb); - }, - getPeerCount: function(cb){ - postData({call: "getPeerCount"}, cb); - }, - getBalanceAt: function(address, cb) { - postData({call: "getBalance", args: [address]}, cb); - }, - getTransactionsFor: function(address, cb) { - postData({call: "getTransactionsFor", args: [address]}, cb); - }, - - getSecretToAddress: function(sec, cb) { - postData({call: "getSecretToAddress", args: [sec]}, cb); - }, - - /* - watch: function(address, storageAddrOrCb, cb) { - var ev; - if(cb === undefined) { - cb = storageAddrOrCb; - storageAddrOrCb = ""; - ev = "object:"+address; - } else { - ev = "storage:"+address+":"+storageAddrOrCb; - } - - eth.on(ev, cb) - - postData({call: "watch", args: [address, storageAddrOrCb]}); - }, - - disconnect: function(address, storageAddrOrCb, cb) { - var ev; - if(cb === undefined) { - cb = storageAddrOrCb; - storageAddrOrCb = ""; - ev = "object:"+address; - } else { - ev = "storage:"+address+":"+storageAddrOrCb; - } - - eth.off(ev, cb) - - postData({call: "disconnect", args: [address, storageAddrOrCb]}); - }, - */ - - watch: function(options) { - var filter = new Filter(options); - filter.number = newWatchNum().toString() - - postData({call: "watch", args: [options, filter.number]}) - - return filter; - }, - - set: function(props) { - postData({call: "set", args: props}); - }, - - on: function(event, cb) { - if(eth._onCallbacks[event] === undefined) { - eth._onCallbacks[event] = []; - } - - eth._onCallbacks[event].push(cb); - - return this - }, - - off: function(event, cb) { - if(eth._onCallbacks[event] !== undefined) { - var callbacks = eth._onCallbacks[event]; - for(var i = 0; i < callbacks.length; i++) { - if(callbacks[i] === cb) { - delete callbacks[i]; - } - } - } - - return this - }, - - trigger: function(event, data) { - var callbacks = eth._onCallbacks[event]; - if(callbacks !== undefined) { - for(var i = 0; i < callbacks.length; i++) { - // Figure out whether the returned data was an array - // array means multiple return arguments (multiple params) - if(data instanceof Array) { - callbacks[i].apply(this, data); - } else { - callbacks[i].call(this, data); - } - } - } - }, -} - - -var Filter = function(options) { - this.options = options; -}; -Filter.prototype.changed = function(callback) { - // Register the watched:<number>. Qml will call the appropriate event if anything - // interesting happens in the land of Go. - eth.on("watched:"+this.number, callback) -} -Filter.prototype.getMessages = function(cb) { - return eth.getMessages(this.options, cb) -} - -var watchNum = 0; -function newWatchNum() { - return watchNum++; -} - -function postData(data, cb) { - data._seed = Math.floor(Math.random() * 1000000) - if(cb) { - eth._callbacks[data._seed] = cb; - } - - if(data.args === undefined) { - data.args = []; - } - - navigator.qt.postMessage(JSON.stringify(data)); -} - -navigator.qt.onmessage = function(ev) { - var data = JSON.parse(ev.data) - - if(data._event !== undefined) { - eth.trigger(data._event, data.data); - } else { - if(data._seed) { - var cb = eth._callbacks[data._seed]; - if(cb) { - cb.call(this, data.data) - - // Remove the "trigger" callback - delete eth._callbacks[ev._seed]; - } - } - } -} - -eth.on("chain:changed", function() { -}) - -eth.on("messages", { /* filters */}, function(messages){ -}) - -eth.on("pending:changed", function() { -}) - diff --git a/cmd/mist/assets/ext/ethereum.js/.bowerrc b/cmd/mist/assets/ext/ethereum.js/.bowerrc new file mode 100644 index 000000000..c3a8813e8 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.bowerrc @@ -0,0 +1,5 @@ +{ + "directory": "example/js/", + "cwd": "./", + "analytics": false +}
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.editorconfig b/cmd/mist/assets/ext/ethereum.js/.editorconfig new file mode 100644 index 000000000..60a2751d3 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.gitignore b/cmd/mist/assets/ext/ethereum.js/.gitignore new file mode 100644 index 000000000..399b6dc88 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.gitignore @@ -0,0 +1,18 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile ~/.gitignore_global + +*.swp +/tmp +*/**/*un~ +*un~ +.DS_Store +*/**/.DS_Store +ethereum/ethereum +ethereal/ethereal +example/js +node_modules +bower_components +npm-debug.log diff --git a/cmd/mist/assets/ext/ethereum.js/.jshintrc b/cmd/mist/assets/ext/ethereum.js/.jshintrc new file mode 100644 index 000000000..c0ec5f89d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.jshintrc @@ -0,0 +1,50 @@ +{ + "predef": [ + "console", + "require", + "equal", + "test", + "testBoth", + "testWithDefault", + "raises", + "deepEqual", + "start", + "stop", + "ok", + "strictEqual", + "module", + "expect", + "reject", + "impl" + ], + + "esnext": true, + "proto": true, + "node" : true, + "browser" : true, + "browserify" : true, + + "boss" : true, + "curly": false, + "debug": true, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "shadow": true, + "eqnull": true +}
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.npmignore b/cmd/mist/assets/ext/ethereum.js/.npmignore new file mode 100644 index 000000000..5bbffe4fd --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.npmignore @@ -0,0 +1,9 @@ +example/js +node_modules +test +.gitignore +.editorconfig +.travis.yml +.npmignore +component.json +testling.html
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.travis.yml b/cmd/mist/assets/ext/ethereum.js/.travis.yml new file mode 100644 index 000000000..83b21d840 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.travis.yml @@ -0,0 +1,13 @@ +language: node_js +node_js: + - "0.11" + - "0.10" +before_script: + - npm install + - npm install jshint +script: + - "jshint *.js lib" +after_script: + - npm run-script build + - npm test + diff --git a/cmd/mist/assets/ext/ethereum.js/LICENSE b/cmd/mist/assets/ext/ethereum.js/LICENSE new file mode 100644 index 000000000..0f187b873 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/LICENSE @@ -0,0 +1,14 @@ +This file is part of ethereum.js. + +ethereum.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ethereum.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/README.md b/cmd/mist/assets/ext/ethereum.js/README.md new file mode 100644 index 000000000..02988fe73 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/README.md @@ -0,0 +1,96 @@ +# Ethereum JavaScript API + +This is the Ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API) +which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. It's available on npm as a node module and also for bower and component as an embeddable js + +[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url] + +<!-- [](https://ci.testling.com/ethereum/ethereum.js) --> + +## Installation + +### Node.js + + npm install ethereum.js + +### For browser +Bower + + bower install ethereum.js + +Component + + component install ethereum/ethereum.js + +* Include `ethereum.min.js` in your html file. +* Include [bignumber.js](https://github.com/MikeMcl/bignumber.js/) + +## Usage +Require the library: + + var web3 = require('web3'); + +Set a provider (QtProvider, WebSocketProvider, HttpRpcProvider) + + var web3.setProvider(new web3.providers.WebSocketProvider('ws://localhost:40404/eth')); + +There you go, now you can use it: + +``` +var coinbase = web3.eth.coinbase; +var balance = web3.eth.balanceAt(coinbase); +``` + + +For another example see `example/index.html`. + +## Contribute! + +### Requirements + +* Node.js +* npm +* gulp (build) +* mocha (tests) + +```bash +sudo apt-get update +sudo apt-get install nodejs +sudo apt-get install npm +sudo apt-get install nodejs-legacy +``` + +### Building (gulp) + +```bash +npm run-script build +``` + + +### Testing (mocha) + +```bash +npm test +``` + +**Please note this repo is in it's early stage.** + +If you'd like to run a WebSocket ethereum node check out +[go-ethereum](https://github.com/ethereum/go-ethereum). + +To install ethereum and spawn a node: + +``` +go get github.com/ethereum/go-ethereum/ethereum +ethereum -ws -loglevel=4 +``` + +[npm-image]: https://badge.fury.io/js/ethereum.js.png +[npm-url]: https://npmjs.org/package/ethereum.js +[travis-image]: https://travis-ci.org/ethereum/ethereum.js.svg +[travis-url]: https://travis-ci.org/ethereum/ethereum.js +[dep-image]: https://david-dm.org/ethereum/ethereum.js.svg +[dep-url]: https://david-dm.org/ethereum/ethereum.js +[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg +[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies + diff --git a/cmd/mist/assets/ext/ethereum.js/bower.json b/cmd/mist/assets/ext/ethereum.js/bower.json new file mode 100644 index 000000000..e3a9cb3c5 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/bower.json @@ -0,0 +1,51 @@ +{ + "name": "ethereum.js", + "namespace": "ethereum", + "version": "0.0.10", + "description": "Ethereum Compatible JavaScript API", + "main": ["./dist/ethereum.js", "./dist/ethereum.min.js"], + "dependencies": { + "bignumber.js": ">=2.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/ethereum/ethereum.js.git" + }, + "homepage": "https://github.com/ethereum/ethereum.js", + "bugs": { + "url": "https://github.com/ethereum/ethereum.js/issues" + }, + "keywords": [ + "ethereum", + "javascript", + "API" + ], + "authors": [ + { + "name": "Marek Kotewicz", + "email": "marek@ethdev.com", + "homepage": "https://github.com/debris" + }, + { + "name": "Marian Oancea", + "email": "marian@ethdev.com", + "homepage": "https://github.com/cubedro" + } + ], + "license": "LGPL-3.0", + "ignore": [ + "example", + "lib", + "node_modules", + "package.json", + ".bowerrc", + ".editorconfig", + ".gitignore", + ".jshintrc", + ".npmignore", + ".travis.yml", + "gulpfile.js", + "index.js", + "**/*.txt" + ] +} diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js new file mode 100644 index 000000000..6e6c5020c --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js @@ -0,0 +1,1198 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file abi.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var BigNumber = require('bignumber.js'); // jshint ignore:line +*/} + +var web3 = require('./web3'); // jshint ignore:line + +BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_DOWN }); + +var ETH_PADDING = 32; + +/// method signature length in bytes +var ETH_METHOD_SIGNATURE_LENGTH = 4; + +/// Finds first index of array element matching pattern +/// @param array +/// @param callback pattern +/// @returns index of element +var findIndex = function (array, callback) { + var end = false; + var i = 0; + for (; i < array.length && !end; i++) { + end = callback(array[i]); + } + return end ? i - 1 : -1; +}; + +/// @returns a function that is used as a pattern for 'findIndex' +var findMethodIndex = function (json, methodName) { + return findIndex(json, function (method) { + return method.name === methodName; + }); +}; + +/// @returns method with given method name +var getMethodWithName = function (json, methodName) { + var index = findMethodIndex(json, methodName); + if (index === -1) { + console.error('method ' + methodName + ' not found in the abi'); + return undefined; + } + return json[index]; +}; + +/// @param string string to be padded +/// @param number of characters that result string should have +/// @param sign, by default 0 +/// @returns right aligned string +var padLeft = function (string, chars, sign) { + return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; +}; + +/// @param expected type prefix (string) +/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false +var prefixedType = function (prefix) { + return function (type) { + return type.indexOf(prefix) === 0; + }; +}; + +/// @param expected type name (string) +/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false +var namedType = function (name) { + return function (type) { + return name === type; + }; +}; + +var arrayType = function (type) { + return type.slice(-2) === '[]'; +}; + +/// Formats input value to byte representation of int +/// If value is negative, return it's two's complement +/// If the value is floating point, round it down +/// @returns right-aligned byte representation of int +var formatInputInt = function (value) { + var padding = ETH_PADDING * 2; + if (value instanceof BigNumber || typeof value === 'number') { + if (typeof value === 'number') + value = new BigNumber(value); + value = value.round(); + + if (value.lessThan(0)) + value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1); + value = value.toString(16); + } + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else if (typeof value === 'string') + value = formatInputInt(new BigNumber(value)); + else + value = (+value).toString(16); + return padLeft(value, padding); +}; + +/// Formats input value to byte representation of string +/// @returns left-algined byte representation of string +var formatInputString = function (value) { + return web3.fromAscii(value, ETH_PADDING).substr(2); +}; + +/// Formats input value to byte representation of bool +/// @returns right-aligned byte representation bool +var formatInputBool = function (value) { + return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); +}; + +/// Formats input value to byte representation of real +/// Values are multiplied by 2^m and encoded as integers +/// @returns byte representation of real +var formatInputReal = function (value) { + return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); +}; + +var dynamicTypeBytes = function (type, value) { + // TODO: decide what to do with array of strings + if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. + return formatInputInt(value.length); + return ""; +}; + +/// Setups input formatters for solidity types +/// @returns an array of input formatters +var setupInputTypes = function () { + + return [ + { type: prefixedType('uint'), format: formatInputInt }, + { type: prefixedType('int'), format: formatInputInt }, + { type: prefixedType('hash'), format: formatInputInt }, + { type: prefixedType('string'), format: formatInputString }, + { type: prefixedType('real'), format: formatInputReal }, + { type: prefixedType('ureal'), format: formatInputReal }, + { type: namedType('address'), format: formatInputInt }, + { type: namedType('bool'), format: formatInputBool } + ]; +}; + +var inputTypes = setupInputTypes(); + +/// Formats input params to bytes +/// @param contract json abi +/// @param name of the method that we want to use +/// @param array of params that will be formatted to bytes +/// @returns bytes representation of input params +var toAbiInput = function (json, methodName, params) { + var bytes = ""; + + var method = getMethodWithName(json, methodName); + var padding = ETH_PADDING * 2; + + /// first we iterate in search for dynamic + method.inputs.forEach(function (input, index) { + bytes += dynamicTypeBytes(input.type, params[index]); + }); + + method.inputs.forEach(function (input, i) { + var typeMatch = false; + for (var j = 0; j < inputTypes.length && !typeMatch; j++) { + typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]); + } + if (!typeMatch) { + console.error('input parser does not support type: ' + method.inputs[i].type); + } + + var formatter = inputTypes[j - 1].format; + var toAppend = ""; + + if (arrayType(method.inputs[i].type)) + toAppend = params[i].reduce(function (acc, curr) { + return acc + formatter(curr); + }, ""); + else + toAppend = formatter(params[i]); + + bytes += toAppend; + }); + return bytes; +}; + +/// Check if input value is negative +/// @param value is hex format +/// @returns true if it is negative, otherwise false +var signedIsNegative = function (value) { + return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1'; +}; + +/// Formats input right-aligned input bytes to int +/// @returns right-aligned input bytes formatted to int +var formatOutputInt = function (value) { + value = value || "0"; + // check if it's negative number + // it it is, return two's complement + if (signedIsNegative(value)) { + return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1); + } + return new BigNumber(value, 16); +}; + +/// Formats big right-aligned input bytes to uint +/// @returns right-aligned input bytes formatted to uint +var formatOutputUInt = function (value) { + value = value || "0"; + return new BigNumber(value, 16); +}; + +/// @returns input bytes formatted to real +var formatOutputReal = function (value) { + return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); +}; + +/// @returns input bytes formatted to ureal +var formatOutputUReal = function (value) { + return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); +}; + +/// @returns right-aligned input bytes formatted to hex +var formatOutputHash = function (value) { + return "0x" + value; +}; + +/// @returns right-aligned input bytes formatted to bool +var formatOutputBool = function (value) { + return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; +}; + +/// @returns left-aligned input bytes formatted to ascii string +var formatOutputString = function (value) { + return web3.toAscii(value); +}; + +/// @returns right-aligned input bytes formatted to address +var formatOutputAddress = function (value) { + return "0x" + value.slice(value.length - 40, value.length); +}; + +var dynamicBytesLength = function (type) { + if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. + return ETH_PADDING * 2; + return 0; +}; + +/// Setups output formaters for solidity types +/// @returns an array of output formatters +var setupOutputTypes = function () { + + return [ + { type: prefixedType('uint'), format: formatOutputUInt }, + { type: prefixedType('int'), format: formatOutputInt }, + { type: prefixedType('hash'), format: formatOutputHash }, + { type: prefixedType('string'), format: formatOutputString }, + { type: prefixedType('real'), format: formatOutputReal }, + { type: prefixedType('ureal'), format: formatOutputUReal }, + { type: namedType('address'), format: formatOutputAddress }, + { type: namedType('bool'), format: formatOutputBool } + ]; +}; + +var outputTypes = setupOutputTypes(); + +/// Formats output bytes back to param list +/// @param contract json abi +/// @param name of the method that we want to use +/// @param bytes representtion of output +/// @returns array of output params +var fromAbiOutput = function (json, methodName, output) { + + output = output.slice(2); + var result = []; + var method = getMethodWithName(json, methodName); + var padding = ETH_PADDING * 2; + + var dynamicPartLength = method.outputs.reduce(function (acc, curr) { + return acc + dynamicBytesLength(curr.type); + }, 0); + + var dynamicPart = output.slice(0, dynamicPartLength); + output = output.slice(dynamicPartLength); + + method.outputs.forEach(function (out, i) { + var typeMatch = false; + for (var j = 0; j < outputTypes.length && !typeMatch; j++) { + typeMatch = outputTypes[j].type(method.outputs[i].type); + } + + if (!typeMatch) { + console.error('output parser does not support type: ' + method.outputs[i].type); + } + + var formatter = outputTypes[j - 1].format; + if (arrayType(method.outputs[i].type)) { + var size = formatOutputUInt(dynamicPart.slice(0, padding)); + dynamicPart = dynamicPart.slice(padding); + var array = []; + for (var k = 0; k < size; k++) { + array.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } + result.push(array); + } + else if (prefixedType('string')(method.outputs[i].type)) { + dynamicPart = dynamicPart.slice(padding); + result.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } else { + result.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } + }); + + return result; +}; + +/// @returns display name for method eg. multiply(uint256) -> multiply +var methodDisplayName = function (method) { + var length = method.indexOf('('); + return length !== -1 ? method.substr(0, length) : method; +}; + +/// @returns overloaded part of method's name +var methodTypeName = function (method) { + /// TODO: make it not vulnerable + var length = method.indexOf('('); + return length !== -1 ? method.substr(length + 1, method.length - 1 - (length + 1)) : ""; +}; + +/// @param json abi for contract +/// @returns input parser object for given json abi +var inputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + var displayName = methodDisplayName(method.name); + var typeName = methodTypeName(method.name); + + var impl = function () { + var params = Array.prototype.slice.call(arguments); + return toAbiInput(json, method.name, params); + }; + + if (parser[displayName] === undefined) { + parser[displayName] = impl; + } + + parser[displayName][typeName] = impl; + }); + + return parser; +}; + +/// @param json abi for contract +/// @returns output parser for given json abi +var outputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + + var displayName = methodDisplayName(method.name); + var typeName = methodTypeName(method.name); + + var impl = function (output) { + return fromAbiOutput(json, method.name, output); + }; + + if (parser[displayName] === undefined) { + parser[displayName] = impl; + } + + parser[displayName][typeName] = impl; + }); + + return parser; +}; + +/// @param method name for which we want to get method signature +/// @returns (promise) contract method signature for method with given name +var methodSignature = function (name) { + return web3.sha3(web3.fromAscii(name)).slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2); +}; + +module.exports = { + inputParser: inputParser, + outputParser: outputParser, + methodSignature: methodSignature, + methodDisplayName: methodDisplayName, + methodTypeName: methodTypeName, + getMethodWithName: getMethodWithName +}; + + +},{"./web3":7}],2:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file contract.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line +var abi = require('./abi'); + +/** + * This method should be called when we want to call / transact some solidity method from javascript + * it returns an object which has same methods available as solidity contract description + * usage example: + * + * var abi = [{ + * name: 'myMethod', + * inputs: [{ name: 'a', type: 'string' }], + * outputs: [{name: 'd', type: 'string' }] + * }]; // contract abi + * + * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object + * + * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default) + * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit) + * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact + * + * @param address - address of the contract, which should be called + * @param desc - abi json description of the contract, which is being created + * @returns contract object + */ + +var contract = function (address, desc) { + + desc.forEach(function (method) { + // workaround for invalid assumption that method.name is the full anonymous prototype of the method. + // it's not. it's just the name. the rest of the code assumes it's actually the anonymous + // prototype, so we make it so as a workaround. + if (method.name.indexOf('(') === -1) { + var displayName = method.name; + var typeName = method.inputs.map(function(i){return i.type; }).join(); + method.name = displayName + '(' + typeName + ')'; + } + }); + + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var result = {}; + + result.call = function (options) { + result._isTransact = false; + result._options = options; + return result; + }; + + result.transact = function (options) { + result._isTransact = true; + result._options = options; + return result; + }; + + result._options = {}; + ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) { + result[p] = function (v) { + result._options[p] = v; + return result; + }; + }); + + + desc.forEach(function (method) { + + var displayName = abi.methodDisplayName(method.name); + var typeName = abi.methodTypeName(method.name); + + var impl = function () { + var params = Array.prototype.slice.call(arguments); + var signature = abi.methodSignature(method.name); + var parsed = inputParser[displayName][typeName].apply(null, params); + + var options = result._options || {}; + options.to = address; + options.data = signature + parsed; + + var isTransact = result._isTransact === true || (result._isTransact !== false && !method.constant); + var collapse = options.collapse !== false; + + // reset + result._options = {}; + result._isTransact = null; + + if (isTransact) { + // it's used byt natspec.js + // TODO: figure out better way to solve this + web3._currentContractAbi = desc; + web3._currentContractAddress = address; + web3._currentContractMethodName = method.name; + web3._currentContractMethodParams = params; + + // transactions do not have any output, cause we do not know, when they will be processed + web3.eth.transact(options); + return; + } + + var output = web3.eth.call(options); + var ret = outputParser[displayName][typeName](output); + if (collapse) + { + if (ret.length === 1) + ret = ret[0]; + else if (ret.length === 0) + ret = null; + } + return ret; + }; + + if (result[displayName] === undefined) { + result[displayName] = impl; + } + + result[displayName][typeName] = impl; + + }); + + return result; +}; + +module.exports = contract; + + +},{"./abi":1,"./web3":7}],3:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file filter.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line + +/// should be used when we want to watch something +/// it's using inner polling mechanism and is notified about changes +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + this.id = impl.newFilter(options); + web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); +}; + +/// alias for changed* +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +/// gets called when there is new eth/shh message +Filter.prototype.changed = function(callback) { + this.callbacks.push(callback); +}; + +/// trigger calling new message from people +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]); + } + } +}; + +/// should be called to uninstall current filter +Filter.prototype.uninstall = function() { + this.impl.uninstallFilter(this.id); + web3.provider.stopPolling(this.id); +}; + +/// should be called to manually trigger getting latest messages from the client +Filter.prototype.messages = function() { + return this.impl.getMessages(this.id); +}; + +/// alias for messages +Filter.prototype.logs = function () { + return this.messages(); +}; + +module.exports = Filter; + +},{"./web3":7}],4:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file httpsync.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * @date 2014 + */ + +if ("build" !== 'build') {/* + var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +*/} + +var HttpSyncProvider = function (host) { + this.handlers = []; + 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 request = new XMLHttpRequest(); + request.open('POST', this.host, false); + request.send(JSON.stringify(data)); + + // check request.status + return request.responseText; +}; + +module.exports = HttpSyncProvider; + + +},{}],5:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file providermanager.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line + +/** + * Provider manager object prototype + * It's responsible for passing messages to providers + * If no provider is set it's responsible for queuing requests + * It's also responsible for polling the ethereum node for incoming messages + * Default poll timeout is 12 seconds + * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, + * and provider manager polling mechanism is not used + */ +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); + + // dont call the callback if result is not an array, or empty one + if (result.error || !(result.result instanceof Array) || result.result.length === 0) { + return; + } + + data.callback(result.result); + }); + } + setTimeout(poll, 1000); + }; + poll(); +}; + +/// sends outgoing requests +ProviderManager.prototype.send = function(data) { + + data.args = data.args || []; + data._id = this.id++; + + 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); + + if (result.error) { + console.log(result.error); + return null; + } + + return result.result; +}; + +/// setups provider, which will be used for sending messages +ProviderManager.prototype.set = function(provider) { + this.provider = provider; +}; + +/// this method is only used, when we do not have native qt bindings and have to do polling on our own +/// should be callled, on start watching for eth/shh changes +ProviderManager.prototype.startPolling = function (data, pollId, callback) { + this.polls.push({data: data, id: pollId, callback: callback}); +}; + +/// should be called to stop polling for certain watch changes +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +module.exports = ProviderManager; + + +},{"./web3":7}],6:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file qtsync.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * @date 2014 + */ + +var QtSyncProvider = function () { +}; + +QtSyncProvider.prototype.send = function (payload) { + return navigator.qt.callMethod(JSON.stringify(payload)); +}; + +module.exports = QtSyncProvider; + + +},{}],7:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file web3.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +if ("build" !== 'build') {/* + var BigNumber = require('bignumber.js'); +*/} + +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 [ + { name: 'sha3', call: 'web3_sha3' } + ]; +}; + +/// @returns an array of objects describing web3.eth api methods +var ethMethods = function () { + var blockCall = function (args) { + return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; + }; + + var transactionCall = function (args) { + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + }; + + var uncleCall = function (args) { + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + }; + + var methods = [ + { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'storageAt', call: 'eth_storageAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, + { name: 'block', call: blockCall }, + { name: 'transaction', call: transactionCall }, + { name: 'uncle', call: uncleCall }, + { name: 'compilers', call: 'eth_compilers' }, + { name: 'flush', call: 'eth_flush' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'serpent', call: 'eth_serpent' }, + { name: 'logs', call: 'eth_logs' } + ]; + return methods; +}; + +/// @returns an array of objects describing web3.eth api properties +var ethProperties = function () { + return [ + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} + ]; +}; + +/// @returns an array of objects describing web3.db api methods +var dbMethods = function () { + return [ + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_getString' } + ]; +}; + +/// @returns an array of objects describing web3.shh api methods +var shhMethods = function () { + return [ + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } + ]; +}; + +/// @returns an array of objects describing web3.eth.watch api methods +var ethWatchMethods = function () { + var newFilter = function (args) { + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; + }; + + return [ + { name: 'newFilter', call: newFilter }, + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_filterLogs' } + ]; +}; + +/// @returns an array of objects describing web3.shh.watch api methods +var shhWatchMethods = function () { + return [ + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessages', call: 'shh_getMessages' } + ]; +}; + +/// creates methods in a given object based on method description on input +/// setups api calls for these methods +var setupMethods = function (obj, methods) { + methods.forEach(function (method) { + obj[method.name] = function () { + 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 + }); + }; + }); +}; + +/// creates properties in a given object based on properties description on input +/// setups api calls for these properties +var setupProperties = function (obj, properties) { + properties.forEach(function (property) { + var proto = {}; + proto.get = function () { + return web3.provider.send({ + call: property.getter + }); + }; + + if (property.setter) { + proto.set = function (val) { + return web3.provider.send({ + call: property.setter, + args: [val] + }); + }; + } + Object.defineProperty(obj, property.name, proto); + }); +}; + +/// setups web3 object, and it's in-browser executed methods +var web3 = { + _callbacks: {}, + _events: {}, + providers: {}, + + toHex: function(str) { + var hex = ""; + for(var i = 0; i < str.length; i++) { + var n = str.charCodeAt(i).toString(16); + hex += n.length < 2 ? '0' + n : n; + } + + return hex; + }, + + /// @returns ascii string representation of hex value prefixed with 0x + toAscii: function(hex) { + // Find termination + var str = ""; + var i = 0, l = hex.length; + if (hex.substring(0, 2) === '0x') + i = 2; + for(; i < l; i+=2) { + var code = parseInt(hex.substr(i, 2), 16); + if(code === 0) { + break; + } + + str += String.fromCharCode(code); + } + + return str; + }, + + /// @returns hex representation (prefixed by 0x) of ascii string + fromAscii: function(str, pad) { + pad = pad === undefined ? 0 : pad; + var hex = this.toHex(str); + while(hex.length < pad*2) + hex += "00"; + return "0x" + hex; + }, + + /// @returns decimal representaton of hex value prefixed by 0x + toDecimal: function (val) { + // remove 0x and place 0, if it's required + val = val.length > 2 ? val.substring(2) : "0"; + return (new BigNumber(val, 16).toString(10)); + }, + + /// @returns hex representation (prefixed by 0x) of decimal value + fromDecimal: function (val) { + return "0x" + (new BigNumber(val).toString(16)); + }, + + /// 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]; + }, + + /// eth object prototype + eth: { + contractFromAbi: function (abi) { + return function(addr) { + // Default to address of Config. TODO: rremove prior to genesis. + addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b'; + var ret = web3.eth.contract(addr, abi); + ret.address = addr; + return ret; + }; + }, + watch: function (params) { + return new web3.filter(params, ethWatch); + } + }, + + /// db object prototype + db: {}, + + /// shh object prototype + shh: { + watch: function (params) { + return new web3.filter(params, shhWatch); + } + }, + + /// @returns true if provider is installed + haveProvider: function() { + return !!web3.provider.provider; + } +}; + +/// setups all api methods +setupMethods(web3, web3Methods()); +setupMethods(web3.eth, ethMethods()); +setupProperties(web3.eth, ethProperties()); +setupMethods(web3.db, dbMethods()); +setupMethods(web3.shh, shhMethods()); + +var ethWatch = { + changed: 'eth_changed' +}; + +setupMethods(ethWatch, ethWatchMethods()); + +var shhWatch = { + changed: 'shh_changed' +}; + +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; + + +},{}],"web3":[function(require,module,exports){ +var web3 = require('./lib/web3'); +var ProviderManager = require('./lib/providermanager'); +web3.provider = new ProviderManager(); +web3.filter = require('./lib/filter'); +web3.providers.HttpSyncProvider = require('./lib/httpsync'); +web3.providers.QtSyncProvider = require('./lib/qtsync'); +web3.eth.contract = require('./lib/contract'); +web3.abi = require('./lib/abi'); + + +module.exports = web3; + +},{"./lib/abi":1,"./lib/contract":2,"./lib/filter":3,"./lib/httpsync":4,"./lib/providermanager":5,"./lib/qtsync":6,"./lib/web3":7}]},{},["web3"]) + + +//# sourceMappingURL=ethereum.js.map diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map new file mode 100644 index 000000000..5017119bc --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map @@ -0,0 +1,29 @@ +{ + "version": 3, + "sources": [ + "node_modules/browserify/node_modules/browser-pack/_prelude.js", + "lib/abi.js", + "lib/contract.js", + "lib/filter.js", + "lib/httpsync.js", + "lib/providermanager.js", + "lib/qtsync.js", + "lib/web3.js", + "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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "file": "generated.js", + "sourceRoot": "", + "sourcesContent": [ + "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar web3 = require('./web3'); // jshint ignore:line\n\nBigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_DOWN });\n\nvar ETH_PADDING = 32;\n\n/// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\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 a function that is used as a pattern for 'findIndex'\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\n/// @returns method with given method name\nvar getMethodWithName = function (json, methodName) {\n var index = findMethodIndex(json, methodName);\n if (index === -1) {\n console.error('method ' + methodName + ' not found in the abi');\n return undefined;\n }\n return json[index];\n};\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/// @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\nvar arrayType = function (type) {\n return type.slice(-2) === '[]';\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 = ETH_PADDING * 2;\n if (value instanceof BigNumber || typeof value === 'number') {\n if (typeof value === 'number')\n value = new BigNumber(value);\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 web3.fromAscii(value, 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\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 formatInputInt(value.length); \n return \"\";\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar setupInputTypes = function () {\n \n return [\n { type: prefixedType('uint'), format: formatInputInt },\n { type: prefixedType('int'), format: formatInputInt },\n { type: prefixedType('hash'), format: formatInputInt },\n { type: prefixedType('string'), format: formatInputString }, \n { type: prefixedType('real'), format: formatInputReal },\n { type: prefixedType('ureal'), format: formatInputReal },\n { type: namedType('address'), format: formatInputInt },\n { type: namedType('bool'), format: formatInputBool }\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\n/// Formats input params to bytes\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n\n var method = getMethodWithName(json, methodName);\n var padding = ETH_PADDING * 2;\n\n /// first we iterate in search for dynamic \n method.inputs.forEach(function (input, index) {\n bytes += dynamicTypeBytes(input.type, params[index]);\n });\n\n method.inputs.forEach(function (input, i) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n console.error('input parser does not support type: ' + method.inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n var toAppend = \"\";\n\n if (arrayType(method.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\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 web3.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\nvar dynamicBytesLength = function (type) {\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return ETH_PADDING * 2;\n return 0;\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar setupOutputTypes = function () {\n\n return [\n { type: prefixedType('uint'), format: formatOutputUInt },\n { type: prefixedType('int'), format: formatOutputInt },\n { type: prefixedType('hash'), format: formatOutputHash },\n { type: prefixedType('string'), format: formatOutputString },\n { type: prefixedType('real'), format: formatOutputReal },\n { type: prefixedType('ureal'), format: formatOutputUReal },\n { type: namedType('address'), format: formatOutputAddress },\n { type: namedType('bool'), format: formatOutputBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\n/// Formats output bytes back to param list\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param bytes representtion of output \n/// @returns array of output params \nvar fromAbiOutput = function (json, methodName, output) {\n \n output = output.slice(2);\n var result = [];\n var method = getMethodWithName(json, methodName);\n var padding = ETH_PADDING * 2;\n\n var dynamicPartLength = method.outputs.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 method.outputs.forEach(function (out, i) {\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(method.outputs[i].type);\n }\n\n if (!typeMatch) {\n console.error('output parser does not support type: ' + method.outputs[i].type);\n }\n\n var formatter = outputTypes[j - 1].format;\n if (arrayType(method.outputs[i].type)) {\n var size = 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 (prefixedType('string')(method.outputs[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/// @returns display name for method eg. multiply(uint256) -> multiply\nvar methodDisplayName = function (method) {\n var length = method.indexOf('('); \n return length !== -1 ? method.substr(0, length) : method;\n};\n\n/// @returns overloaded part of method's name\nvar methodTypeName = function (method) {\n /// TODO: make it not vulnerable\n var length = method.indexOf('(');\n return length !== -1 ? method.substr(length + 1, method.length - 1 - (length + 1)) : \"\";\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = methodDisplayName(method.name); \n var typeName = methodTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, 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 = methodDisplayName(method.name); \n var typeName = methodTypeName(method.name);\n\n var impl = function (output) {\n return fromAbiOutput(json, method.name, 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 method name for which we want to get method signature\n/// @returns (promise) contract method signature for method with given name\nvar methodSignature = function (name) {\n return web3.sha3(web3.fromAscii(name)).slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2);\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature,\n methodDisplayName: methodDisplayName,\n methodTypeName: methodTypeName,\n getMethodWithName: getMethodWithName\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\nvar abi = require('./abi');\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 desc.forEach(function (method) {\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 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 inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var result = {};\n\n result.call = function (options) {\n result._isTransact = false;\n result._options = options;\n return result;\n };\n\n result.transact = function (options) {\n result._isTransact = true;\n result._options = options;\n return result;\n };\n\n result._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n result[p] = function (v) {\n result._options[p] = v;\n return result;\n };\n });\n\n\n desc.forEach(function (method) {\n\n var displayName = abi.methodDisplayName(method.name);\n var typeName = abi.methodTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.methodSignature(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = result._options || {};\n options.to = address;\n options.data = signature + parsed;\n \n var isTransact = result._isTransact === true || (result._isTransact !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n result._options = {};\n result._isTransact = null;\n\n if (isTransact) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = desc;\n web3._currentContractAddress = address;\n web3._currentContractMethodName = method.name;\n web3._currentContractMethodParams = params;\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 (result[displayName] === undefined) {\n result[displayName] = impl;\n }\n\n result[displayName][typeName] = impl;\n\n });\n\n return result;\n};\n\nmodule.exports = contract;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\n\n/// should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\nvar Filter = function(options, impl) {\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 <http://www.gnu.org/licenses/>.\n*/\n/** @file httpsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpSyncProvider = function (host) {\n this.handlers = [];\n this.host = host || 'http://localhost:8080';\n};\n\n/// Transforms inner message to proper jsonrpc object\n/// @param inner message object\n/// @returns jsonrpc object\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\n/// Transforms jsonrpc object to inner message\n/// @param incoming jsonrpc message \n/// @returns inner message object\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\nHttpSyncProvider.prototype.send = function (payload) {\n var data = formatJsonRpcObject(payload);\n \n var request = new XMLHttpRequest();\n request.open('POST', this.host, false);\n request.send(JSON.stringify(data));\n \n // check request.status\n return request.responseText;\n};\n\nmodule.exports = HttpSyncProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nvar web3 = require('./web3'); // jshint ignore:line\n\n/**\n * Provider manager object prototype\n * It's responsible for passing messages to providers\n * If no provider is set it's responsible for queuing requests\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 12 seconds\n * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,\n * and provider manager polling mechanism is not used\n */\nvar ProviderManager = function() {\n this.polls = [];\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n var result = self.provider.send(data.data);\n \n result = JSON.parse(result);\n \n // dont call the callback if result is not an array, or empty one\n if (result.error || !(result.result instanceof Array) || result.result.length === 0) {\n return;\n }\n\n data.callback(result.result);\n });\n }\n setTimeout(poll, 1000);\n };\n poll();\n};\n\n/// sends outgoing requests\nProviderManager.prototype.send = function(data) {\n\n data.args = data.args || [];\n data._id = this.id++;\n\n if (this.provider === undefined) {\n console.error('provider is not set');\n return null; \n }\n\n //TODO: handle error here? \n var result = this.provider.send(data);\n result = JSON.parse(result);\n\n if (result.error) {\n console.log(result.error);\n return null;\n }\n\n return result.result;\n};\n\n/// setups provider, which will be used for sending messages\nProviderManager.prototype.set = function(provider) {\n this.provider = provider;\n};\n\n/// this method is only used, when we do not have native qt bindings and have to do polling on our own\n/// should be callled, on start watching for eth/shh changes\nProviderManager.prototype.startPolling = function (data, pollId, callback) {\n this.polls.push({data: data, id: pollId, callback: callback});\n};\n\n/// should be called to stop polling for certain watch changes\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nmodule.exports = ProviderManager;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file qtsync.js\n * @authors:\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * @date 2014\n */\n\nvar QtSyncProvider = function () {\n};\n\nQtSyncProvider.prototype.send = function (payload) {\n return navigator.qt.callMethod(JSON.stringify(payload));\n};\n\nmodule.exports = QtSyncProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke <jeff@ethdev.com>\n * Marek Kotewicz <marek@ethdev.com>\n * Marian Oancea <marian@ethdev.com>\n * Gav Wood <g@ethdev.com>\n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js');\n*/}\n\nvar 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 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 ascii string representation of hex value prefixed with 0x\n 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 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\n /// @returns hex representation (prefixed by 0x) of ascii string\n fromAscii: function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = this.toHex(str);\n while(hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n },\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 watch: function (params) {\n return new web3.filter(params, ethWatch);\n }\n },\n\n /// db object prototype\n db: {},\n\n /// shh object prototype\n shh: {\n watch: function (params) {\n return new web3.filter(params, 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", + "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/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js new file mode 100644 index 000000000..b5b0fb547 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js @@ -0,0 +1 @@ +require=function t(e,n,r){function i(a,f){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!f&&u)return u(a,!0);if(o)return o(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var c=n[a]={exports:{}};e[a][0].call(c.exports,function(t){var n=e[a][1][t];return i(n?n:t)},c,c.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<r.length;a++)i(r[a]);return i}({1:[function(t,e){var n=t("./web3");BigNumber.config({ROUNDING_MODE:BigNumber.ROUND_DOWN});var r=32,i=4,o=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},a=function(t,e){return o(t,function(t){return t.name===e})},f=function(t,e){var n=a(t,e);return-1===n?void console.error("method "+e+" not found in the abi"):t[n]},u=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},s=function(t){return function(e){return 0===e.indexOf(t)}},c=function(t){return function(e){return t===e}},l=function(t){return"[]"===t.slice(-2)},h=function(t){var e=2*r;return t instanceof BigNumber||"number"==typeof t?("number"==typeof t&&(t=new BigNumber(t)),t=t.round(),t.lessThan(0)&&(t=new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(t).plus(1)),t=t.toString(16)):t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?h(new BigNumber(t)):(+t).toString(16),u(t,e)},p=function(t){return n.fromAscii(t,r).substr(2)},d=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},m=function(t){return h(new BigNumber(t).times(new BigNumber(2).pow(128)))},g=function(t,e){return l(t)||"string"===t?h(e.length):""},v=function(){return[{type:s("uint"),format:h},{type:s("int"),format:h},{type:s("hash"),format:h},{type:s("string"),format:p},{type:s("real"),format:m},{type:s("ureal"),format:m},{type:c("address"),format:h},{type:c("bool"),format:d}]},b=v(),y=function(t,e,n){var r="",i=f(t,e);return i.inputs.forEach(function(t,e){r+=g(t.type,n[e])}),i.inputs.forEach(function(t,e){for(var o=!1,a=0;a<b.length&&!o;a++)o=b[a].type(i.inputs[e].type,n[e]);o||console.error("input parser does not support type: "+i.inputs[e].type);var f=b[a-1].format,u="";u=l(i.inputs[e].type)?n[e].reduce(function(t,e){return t+f(e)},""):f(n[e]),r+=u}),r},_=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},w=function(t){return t=t||"0",_(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},N=function(t){return t=t||"0",new BigNumber(t,16)},x=function(t){return w(t).dividedBy(new BigNumber(2).pow(128))},B=function(t){return N(t).dividedBy(new BigNumber(2).pow(128))},A=function(t){return"0x"+t},S=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},O=function(t){return n.toAscii(t)},P=function(t){return"0x"+t.slice(t.length-40,t.length)},E=function(t){return l(t)||"string"===t?2*r:0},k=function(){return[{type:s("uint"),format:N},{type:s("int"),format:w},{type:s("hash"),format:A},{type:s("string"),format:O},{type:s("real"),format:x},{type:s("ureal"),format:B},{type:c("address"),format:P},{type:c("bool"),format:S}]},F=k(),T=function(t,e,n){n=n.slice(2);var i=[],o=f(t,e),a=2*r,u=o.outputs.reduce(function(t,e){return t+E(e.type)},0),c=n.slice(0,u);return n=n.slice(u),o.outputs.forEach(function(t,e){for(var r=!1,f=0;f<F.length&&!r;f++)r=F[f].type(o.outputs[e].type);r||console.error("output parser does not support type: "+o.outputs[e].type);var u=F[f-1].format;if(l(o.outputs[e].type)){var h=N(c.slice(0,a));c=c.slice(a);for(var p=[],d=0;h>d;d++)p.push(u(n.slice(0,a))),n=n.slice(a);i.push(p)}else s("string")(o.outputs[e].type)?(c=c.slice(a),i.push(u(n.slice(0,a))),n=n.slice(a)):(i.push(u(n.slice(0,a))),n=n.slice(a))}),i},M=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},D=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)):""},C=function(t){var e={};return t.forEach(function(n){var r=M(n.name),i=D(n.name),o=function(){var e=Array.prototype.slice.call(arguments);return y(t,n.name,e)};void 0===e[r]&&(e[r]=o),e[r][i]=o}),e},q=function(t){var e={};return t.forEach(function(n){var r=M(n.name),i=D(n.name),o=function(e){return T(t,n.name,e)};void 0===e[r]&&(e[r]=o),e[r][i]=o}),e},I=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*i)};e.exports={inputParser:C,outputParser:q,methodSignature:I,methodDisplayName:M,methodTypeName:D,getMethodWithName:f}},{"./web3":7}],2:[function(t,e){var n=t("./web3"),r=t("./abi"),i=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 i=r.inputParser(e),o=r.outputParser(e),a={};return a.call=function(t){return a._isTransact=!1,a._options=t,a},a.transact=function(t){return a._isTransact=!0,a._options=t,a},a._options={},["gas","gasPrice","value","from"].forEach(function(t){a[t]=function(e){return a._options[t]=e,a}}),e.forEach(function(f){var u=r.methodDisplayName(f.name),s=r.methodTypeName(f.name),c=function(){var c=Array.prototype.slice.call(arguments),l=r.methodSignature(f.name),h=i[u][s].apply(null,c),p=a._options||{};p.to=t,p.data=l+h;var d=a._isTransact===!0||a._isTransact!==!1&&!f.constant,m=p.collapse!==!1;if(a._options={},a._isTransact=null,d)return n._currentContractAbi=e,n._currentContractAddress=t,n._currentContractMethodName=f.name,n._currentContractMethodParams=c,void n.eth.transact(p);var g=n.eth.call(p),v=o[u][s](g);return m&&(1===v.length?v=v[0]:0===v.length&&(v=null)),v};void 0===a[u]&&(a[u]=c),a[u][s]=c}),a};e.exports=i},{"./abi":1,"./web3":7}],3:[function(t,e){var n=t("./web3"),r=function(t,e){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;e<this.callbacks.length;e++)for(var n=0;n<t.length;n++)this.callbacks[e].call(this,t[n])},r.prototype.uninstall=function(){this.impl.uninstallFilter(this.id),n.provider.stopPolling(this.id)},r.prototype.messages=function(){return this.impl.getMessages(this.id)},r.prototype.logs=function(){return this.messages()},e.exports=r},{"./web3":7}],4:[function(t,e){function n(t){return{jsonrpc:"2.0",method:t.call,params:t.args,id:t._id}}var r=function(t){this.handlers=[],this.host=t||"http://localhost:8080"};r.prototype.send=function(t){var e=n(t),r=new XMLHttpRequest;return r.open("POST",this.host,!1),r.send(JSON.stringify(e)),r.responseText},e.exports=r},{}],5:[function(t,e){var n=(t("./web3"),function(){this.polls=[],this.provider=void 0,this.id=1;var t=this,e=function(){t.provider&&t.polls.forEach(function(e){e.data._id=t.id,t.id++;var n=t.provider.send(e.data);n=JSON.parse(n),!n.error&&n.result instanceof Array&&0!==n.result.length&&e.callback(n.result)}),setTimeout(e,1e3)};e()});n.prototype.send=function(t){if(t.args=t.args||[],t._id=this.id++,void 0===this.provider)return console.error("provider is not set"),null;var e=this.provider.send(t);return e=JSON.parse(e),e.error?(console.log(e.error),null):e.result},n.prototype.set=function(t){this.provider=t},n.prototype.startPolling=function(t,e,n){this.polls.push({data:t,id:e,callback:n})},n.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},e.exports=n},{"./web3":7}],6:[function(t,e){var n=function(){};n.prototype.send=function(t){return navigator.qt.callMethod(JSON.stringify(t))},e.exports=n},{}],7:[function(t,e){var n=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"],r=function(){return[{name:"sha3",call:"web3_sha3"}]},i=function(){var t=function(t){return"string"==typeof t[0]?"eth_blockByHash":"eth_blockByNumber"},e=function(t){return"string"==typeof t[0]?"eth_transactionByHash":"eth_transactionByNumber"},n=function(t){return"string"==typeof t[0]?"eth_uncleByHash":"eth_uncleByNumber"},r=[{name:"balanceAt",call:"eth_balanceAt"},{name:"stateAt",call:"eth_stateAt"},{name:"storageAt",call:"eth_storageAt"},{name:"countAt",call:"eth_countAt"},{name:"codeAt",call:"eth_codeAt"},{name:"transact",call:"eth_transact"},{name:"call",call:"eth_call"},{name:"block",call:t},{name:"transaction",call:e},{name:"uncle",call:n},{name:"compilers",call:"eth_compilers"},{name:"flush",call:"eth_flush"},{name:"lll",call:"eth_lll"},{name:"solidity",call:"eth_solidity"},{name:"serpent",call:"eth_serpent"},{name:"logs",call:"eth_logs"}];return r},o=function(){return[{name:"coinbase",getter:"eth_coinbase",setter:"eth_setCoinbase"},{name:"listening",getter:"eth_listening",setter:"eth_setListening"},{name:"mining",getter:"eth_mining",setter:"eth_setMining"},{name:"gasPrice",getter:"eth_gasPrice"},{name:"accounts",getter:"eth_accounts"},{name:"peerCount",getter:"eth_peerCount"},{name:"defaultBlock",getter:"eth_defaultBlock",setter:"eth_setDefaultBlock"},{name:"number",getter:"eth_number"}]},a=function(){return[{name:"put",call:"db_put"},{name:"get",call:"db_get"},{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"}]},f=function(){return[{name:"post",call:"shh_post"},{name:"newIdentity",call:"shh_newIdentity"},{name:"haveIdentity",call:"shh_haveIdentity"},{name:"newGroup",call:"shh_newGroup"},{name:"addToGroup",call:"shh_addToGroup"}]},u=function(){var t=function(t){return"string"==typeof t[0]?"eth_newFilterString":"eth_newFilter"};return[{name:"newFilter",call:t},{name:"uninstallFilter",call:"eth_uninstallFilter"},{name:"getMessages",call:"eth_filterLogs"}]},s=function(){return[{name:"newFilter",call:"shh_newFilter"},{name:"uninstallFilter",call:"shh_uninstallFilter"},{name:"getMessages",call:"shh_getMessages"}]},c=function(t,e){e.forEach(function(e){t[e.name]=function(){var t=Array.prototype.slice.call(arguments),n="function"==typeof e.call?e.call(t):e.call;return h.provider.send({call:n,args:t})}})},l=function(t,e){e.forEach(function(e){var n={};n.get=function(){return h.provider.send({call:e.getter})},e.setter&&(n.set=function(t){return h.provider.send({call:e.setter,args:[t]})}),Object.defineProperty(t,e.name,n)})},h={_callbacks:{},_events:{},providers:{},toHex:function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},toAscii:function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return t=t.length>2?t.substring(2):"0",new BigNumber(t,16).toString(10)},fromDecimal:function(t){return"0x"+new BigNumber(t).toString(16)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,r=0,i=n;e>3e3&&r<i.length-1;)e/=1e3,r++;for(var o=e.toString().length<e.toFixed(2).length?e.toString():e.toFixed(2),a=function(t,e,n){return e+","+n};;){var f=o;if(o=o.replace(/(\d)(\d\d\d[\.\,])/,a),f===o)break}return o+" "+i[r]},eth:{contractFromAbi:function(t){return function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=h.eth.contract(e,t);return n.address=e,n}},watch:function(t){return new h.filter(t,p)}},db:{},shh:{watch:function(t){return new h.filter(t,d)}},haveProvider:function(){return!!h.provider.provider}};c(h,r()),c(h.eth,i()),l(h.eth,o()),c(h.db,a()),c(h.shh,f());var p={changed:"eth_changed"};c(p,u());var d={changed:"shh_changed"};c(d,s()),h.setProvider=function(t){h.provider.set(t)},e.exports=h},{}],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":2,"./lib/filter":3,"./lib/httpsync":4,"./lib/providermanager":5,"./lib/qtsync":6,"./lib/web3":7}]},{},["web3"]);
\ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/example/balance.html b/cmd/mist/assets/ext/ethereum.js/example/balance.html new file mode 100644 index 000000000..4b51c5a7d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/balance.html @@ -0,0 +1,39 @@ +<!doctype> +<html> + +<head> +<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> +<script type="text/javascript" src="../dist/ethereum.js"></script> +<script type="text/javascript"> + + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + + function watchBalance() { + var coinbase = web3.eth.coinbase; + var originalBalance = 0; + + var balance = web3.eth.balanceAt(coinbase); + var originalBalance = web3.toDecimal(balance); + document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...'; + + var filter = web3.eth.watch({address: coinbase}).changed(function() { + balance = web3.eth.balanceAt(coinbase) + var currentBalance = web3.toDecimal(balance); + document.getElementById("current").innerText = 'current: ' + currentBalance; + document.getElementById("diff").innerText = 'diff: ' + (currentBalance - originalBalance); + }); + } + +</script> +</head> +<body> + <h1>coinbase balance</h1> + <button type="button" onClick="watchBalance();">watch balance</button> + <div></div> + <div id="original"></div> + <div id="current"></div> + <div id="diff"></div> +</body> +</html> + diff --git a/cmd/mist/assets/ext/ethereum.js/example/contract.html b/cmd/mist/assets/ext/ethereum.js/example/contract.html new file mode 100644 index 000000000..dccd1a64f --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/contract.html @@ -0,0 +1,73 @@ +<!doctype> +<html> + +<head> +<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> +<script type="text/javascript" src="../dist/ethereum.js"></script> +<script type="text/javascript"> + + var web3 = require('web3'); + web3.setProvider(new web3.providers.HttpSyncProvider()); + + // solidity source code + var source = "" + + "contract test {\n" + + " function multiply(uint a) returns(uint d) {\n" + + " return a * 7;\n" + + " }\n" + + "}\n"; + + // contract description, this will be autogenerated somehow + var desc = [{ + "name": "multiply(uint256)", + "inputs": [ + { + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + var contract; + + function createExampleContract() { + // hide create button + document.getElementById('create').style.visibility = 'hidden'; + document.getElementById('source').innerText = source; + + // create contract + var address = web3.eth.transact({code: web3.eth.solidity(source)}); + contract = web3.eth.contract(address, desc); + document.getElementById('call').style.visibility = 'visible'; + } + + function callExampleContract() { + // this should be generated by ethereum + var param = parseInt(document.getElementById('value').value); + + // call the contract + var res = contract.call().multiply(param); + document.getElementById('result').innerText = res.toString(10); + } + +</script> +</head> +<body> + <h1>contract</h1> + <div id="source"></div> + <div id='create'> + <button type="button" onClick="createExampleContract();">create example contract</button> + </div> + <div id='call' style='visibility: hidden;'> + <input type="number" id="value" onkeyup='callExampleContract()'></input> + </div> + <div id="result"></div> +</body> +</html> + diff --git a/cmd/mist/assets/ext/ethereum.js/example/natspec_contract.html b/cmd/mist/assets/ext/ethereum.js/example/natspec_contract.html new file mode 100644 index 000000000..40561a27c --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/natspec_contract.html @@ -0,0 +1,76 @@ +<!doctype> +<html> + +<head> +<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> +<script type="text/javascript" src="../dist/ethereum.js"></script> +<script type="text/javascript"> + + var web3 = require('web3'); + web3.setProvider(new web3.providers.QtSyncProvider()); + + // solidity source code + var source = "" + + "contract test {\n" + + " /// @notice Will multiply `a` by 7. \n" + + " function multiply(uint a) returns(uint d) {\n" + + " return a * 7;\n" + + " }\n" + + "}\n"; + + // contract description, this will be autogenerated somehow + var desc = [{ + "name": "multiply(uint256)", + "inputs": [ + { + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + var contract; + + function createExampleContract() { + // hide create button + document.getElementById('create').style.visibility = 'hidden'; + document.getElementById('source').innerText = source; + + // create contract + var address = web3.eth.transact({code: web3.eth.solidity(source)}); + contract = web3.eth.contract(address, desc); + document.getElementById('call').style.visibility = 'visible'; + } + + function callExampleContract() { + // this should be generated by ethereum + var param = parseInt(document.getElementById('value').value); + + // transaction does not return any result, cause it's not synchronous and we don't know, + // when it will be processed + contract.transact().multiply(param); + document.getElementById('result').innerText = 'transaction made'; + } + +</script> +</head> +<body> + <h1>contract</h1> + <div id="source"></div> + <div id='create'> + <button type="button" onClick="createExampleContract();">create example contract</button> + </div> + <div id='call' style='visibility: hidden;'> + <input type="number" id="value"></input> + <button type="button" onClick="callExampleContract()">Call Contract</button> + </div> + <div id="result"></div> +</body> +</html> + diff --git a/cmd/mist/assets/ext/ethereum.js/example/node-app.js b/cmd/mist/assets/ext/ethereum.js/example/node-app.js new file mode 100644 index 000000000..8c2fc0ba3 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/node-app.js @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +var web3 = require("../index.js"); + +web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); + +var coinbase = web3.eth.coinbase; +console.log(coinbase); + +var balance = web3.eth.balanceAt(coinbase); +console.log(balance); + diff --git a/cmd/mist/assets/ext/ethereum.js/gulpfile.js b/cmd/mist/assets/ext/ethereum.js/gulpfile.js new file mode 100644 index 000000000..f8f6c96ce --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/gulpfile.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node + +'use strict'; + +var path = require('path'); + +var del = require('del'); +var gulp = require('gulp'); +var browserify = require('browserify'); +var jshint = require('gulp-jshint'); +var uglify = require('gulp-uglify'); +var rename = require('gulp-rename'); +var envify = require('envify/custom'); +var unreach = require('unreachable-branch-transform'); +var source = require('vinyl-source-stream'); +var exorcist = require('exorcist'); +var bower = require('bower'); + +var DEST = './dist/'; + +var build = function(src, dst, ugly) { + var result = browserify({ + debug: true, + insert_global_vars: false, + detectGlobals: false, + bundleExternal: false + }) + .require('./' + src + '.js', {expose: 'web3'}) + .add('./' + src + '.js') + .transform('envify', { + NODE_ENV: 'build' + }) + .transform('unreachable-branch-transform'); + + if (ugly) { + result = result.transform('uglifyify', { + mangle: false, + compress: { + dead_code: false, + conditionals: true, + unused: false, + hoist_funs: true, + hoist_vars: true, + negate_iife: false + }, + beautify: true, + warnings: true + }); + } + + return result.bundle() + .pipe(exorcist(path.join( DEST, dst + '.js.map'))) + .pipe(source(dst + '.js')) + .pipe(gulp.dest( DEST )); +}; + +var uglifyFile = function(file) { + return gulp.src( DEST + file + '.js') + .pipe(uglify()) + .pipe(rename(file + '.min.js')) + .pipe(gulp.dest( DEST )); +}; + +gulp.task('bower', function(cb){ + bower.commands.install().on('end', function (installed){ + console.log(installed); + cb(); + }); +}); + +gulp.task('clean', ['lint'], function(cb) { + del([ DEST ], cb); +}); + +gulp.task('lint', function(){ + return gulp.src(['./*.js', './lib/*.js']) + .pipe(jshint()) + .pipe(jshint.reporter('default')); +}); + +gulp.task('build', ['clean'], function () { + return build('index', 'ethereum', true); +}); + +gulp.task('buildDev', ['clean'], function () { + return build('index', 'ethereum', false); +}); + +gulp.task('uglify', ['build'], function(){ + return uglifyFile('ethereum'); +}); + +gulp.task('uglifyDev', ['buildDev'], function(){ + return uglifyFile('ethereum'); +}); + +gulp.task('watch', function() { + gulp.watch(['./lib/*.js'], ['lint', 'prepare', 'build']); +}); + +gulp.task('release', ['bower', 'lint', 'build', 'uglify']); +gulp.task('dev', ['bower', 'lint', 'buildDev', 'uglifyDev']); +gulp.task('default', ['dev']); + diff --git a/cmd/mist/assets/ext/ethereum.js/index.js b/cmd/mist/assets/ext/ethereum.js/index.js new file mode 100644 index 000000000..76c923722 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/index.js @@ -0,0 +1,11 @@ +var web3 = require('./lib/web3'); +var ProviderManager = require('./lib/providermanager'); +web3.provider = new ProviderManager(); +web3.filter = require('./lib/filter'); +web3.providers.HttpSyncProvider = require('./lib/httpsync'); +web3.providers.QtSyncProvider = require('./lib/qtsync'); +web3.eth.contract = require('./lib/contract'); +web3.abi = require('./lib/abi'); + + +module.exports = web3; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/abi.js b/cmd/mist/assets/ext/ethereum.js/lib/abi.js new file mode 100644 index 000000000..ba47dca73 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/abi.js @@ -0,0 +1,410 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file abi.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var BigNumber = require('bignumber.js'); // jshint ignore:line +} + +var web3 = require('./web3'); // jshint ignore:line + +BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_DOWN }); + +var ETH_PADDING = 32; + +/// method signature length in bytes +var ETH_METHOD_SIGNATURE_LENGTH = 4; + +/// Finds first index of array element matching pattern +/// @param array +/// @param callback pattern +/// @returns index of element +var findIndex = function (array, callback) { + var end = false; + var i = 0; + for (; i < array.length && !end; i++) { + end = callback(array[i]); + } + return end ? i - 1 : -1; +}; + +/// @returns a function that is used as a pattern for 'findIndex' +var findMethodIndex = function (json, methodName) { + return findIndex(json, function (method) { + return method.name === methodName; + }); +}; + +/// @returns method with given method name +var getMethodWithName = function (json, methodName) { + var index = findMethodIndex(json, methodName); + if (index === -1) { + console.error('method ' + methodName + ' not found in the abi'); + return undefined; + } + return json[index]; +}; + +/// @param string string to be padded +/// @param number of characters that result string should have +/// @param sign, by default 0 +/// @returns right aligned string +var padLeft = function (string, chars, sign) { + return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; +}; + +/// @param expected type prefix (string) +/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false +var prefixedType = function (prefix) { + return function (type) { + return type.indexOf(prefix) === 0; + }; +}; + +/// @param expected type name (string) +/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false +var namedType = function (name) { + return function (type) { + return name === type; + }; +}; + +var arrayType = function (type) { + return type.slice(-2) === '[]'; +}; + +/// Formats input value to byte representation of int +/// If value is negative, return it's two's complement +/// If the value is floating point, round it down +/// @returns right-aligned byte representation of int +var formatInputInt = function (value) { + var padding = ETH_PADDING * 2; + if (value instanceof BigNumber || typeof value === 'number') { + if (typeof value === 'number') + value = new BigNumber(value); + value = value.round(); + + if (value.lessThan(0)) + value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1); + value = value.toString(16); + } + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else if (typeof value === 'string') + value = formatInputInt(new BigNumber(value)); + else + value = (+value).toString(16); + return padLeft(value, padding); +}; + +/// Formats input value to byte representation of string +/// @returns left-algined byte representation of string +var formatInputString = function (value) { + return web3.fromAscii(value, ETH_PADDING).substr(2); +}; + +/// Formats input value to byte representation of bool +/// @returns right-aligned byte representation bool +var formatInputBool = function (value) { + return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); +}; + +/// Formats input value to byte representation of real +/// Values are multiplied by 2^m and encoded as integers +/// @returns byte representation of real +var formatInputReal = function (value) { + return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); +}; + +var dynamicTypeBytes = function (type, value) { + // TODO: decide what to do with array of strings + if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. + return formatInputInt(value.length); + return ""; +}; + +/// Setups input formatters for solidity types +/// @returns an array of input formatters +var setupInputTypes = function () { + + return [ + { type: prefixedType('uint'), format: formatInputInt }, + { type: prefixedType('int'), format: formatInputInt }, + { type: prefixedType('hash'), format: formatInputInt }, + { type: prefixedType('string'), format: formatInputString }, + { type: prefixedType('real'), format: formatInputReal }, + { type: prefixedType('ureal'), format: formatInputReal }, + { type: namedType('address'), format: formatInputInt }, + { type: namedType('bool'), format: formatInputBool } + ]; +}; + +var inputTypes = setupInputTypes(); + +/// Formats input params to bytes +/// @param contract json abi +/// @param name of the method that we want to use +/// @param array of params that will be formatted to bytes +/// @returns bytes representation of input params +var toAbiInput = function (json, methodName, params) { + var bytes = ""; + + var method = getMethodWithName(json, methodName); + var padding = ETH_PADDING * 2; + + /// first we iterate in search for dynamic + method.inputs.forEach(function (input, index) { + bytes += dynamicTypeBytes(input.type, params[index]); + }); + + method.inputs.forEach(function (input, i) { + var typeMatch = false; + for (var j = 0; j < inputTypes.length && !typeMatch; j++) { + typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]); + } + if (!typeMatch) { + console.error('input parser does not support type: ' + method.inputs[i].type); + } + + var formatter = inputTypes[j - 1].format; + var toAppend = ""; + + if (arrayType(method.inputs[i].type)) + toAppend = params[i].reduce(function (acc, curr) { + return acc + formatter(curr); + }, ""); + else + toAppend = formatter(params[i]); + + bytes += toAppend; + }); + return bytes; +}; + +/// Check if input value is negative +/// @param value is hex format +/// @returns true if it is negative, otherwise false +var signedIsNegative = function (value) { + return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1'; +}; + +/// Formats input right-aligned input bytes to int +/// @returns right-aligned input bytes formatted to int +var formatOutputInt = function (value) { + value = value || "0"; + // check if it's negative number + // it it is, return two's complement + if (signedIsNegative(value)) { + return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1); + } + return new BigNumber(value, 16); +}; + +/// Formats big right-aligned input bytes to uint +/// @returns right-aligned input bytes formatted to uint +var formatOutputUInt = function (value) { + value = value || "0"; + return new BigNumber(value, 16); +}; + +/// @returns input bytes formatted to real +var formatOutputReal = function (value) { + return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); +}; + +/// @returns input bytes formatted to ureal +var formatOutputUReal = function (value) { + return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); +}; + +/// @returns right-aligned input bytes formatted to hex +var formatOutputHash = function (value) { + return "0x" + value; +}; + +/// @returns right-aligned input bytes formatted to bool +var formatOutputBool = function (value) { + return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; +}; + +/// @returns left-aligned input bytes formatted to ascii string +var formatOutputString = function (value) { + return web3.toAscii(value); +}; + +/// @returns right-aligned input bytes formatted to address +var formatOutputAddress = function (value) { + return "0x" + value.slice(value.length - 40, value.length); +}; + +var dynamicBytesLength = function (type) { + if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. + return ETH_PADDING * 2; + return 0; +}; + +/// Setups output formaters for solidity types +/// @returns an array of output formatters +var setupOutputTypes = function () { + + return [ + { type: prefixedType('uint'), format: formatOutputUInt }, + { type: prefixedType('int'), format: formatOutputInt }, + { type: prefixedType('hash'), format: formatOutputHash }, + { type: prefixedType('string'), format: formatOutputString }, + { type: prefixedType('real'), format: formatOutputReal }, + { type: prefixedType('ureal'), format: formatOutputUReal }, + { type: namedType('address'), format: formatOutputAddress }, + { type: namedType('bool'), format: formatOutputBool } + ]; +}; + +var outputTypes = setupOutputTypes(); + +/// Formats output bytes back to param list +/// @param contract json abi +/// @param name of the method that we want to use +/// @param bytes representtion of output +/// @returns array of output params +var fromAbiOutput = function (json, methodName, output) { + + output = output.slice(2); + var result = []; + var method = getMethodWithName(json, methodName); + var padding = ETH_PADDING * 2; + + var dynamicPartLength = method.outputs.reduce(function (acc, curr) { + return acc + dynamicBytesLength(curr.type); + }, 0); + + var dynamicPart = output.slice(0, dynamicPartLength); + output = output.slice(dynamicPartLength); + + method.outputs.forEach(function (out, i) { + var typeMatch = false; + for (var j = 0; j < outputTypes.length && !typeMatch; j++) { + typeMatch = outputTypes[j].type(method.outputs[i].type); + } + + if (!typeMatch) { + console.error('output parser does not support type: ' + method.outputs[i].type); + } + + var formatter = outputTypes[j - 1].format; + if (arrayType(method.outputs[i].type)) { + var size = formatOutputUInt(dynamicPart.slice(0, padding)); + dynamicPart = dynamicPart.slice(padding); + var array = []; + for (var k = 0; k < size; k++) { + array.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } + result.push(array); + } + else if (prefixedType('string')(method.outputs[i].type)) { + dynamicPart = dynamicPart.slice(padding); + result.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } else { + result.push(formatter(output.slice(0, padding))); + output = output.slice(padding); + } + }); + + return result; +}; + +/// @returns display name for method eg. multiply(uint256) -> multiply +var methodDisplayName = function (method) { + var length = method.indexOf('('); + return length !== -1 ? method.substr(0, length) : method; +}; + +/// @returns overloaded part of method's name +var methodTypeName = function (method) { + /// TODO: make it not vulnerable + var length = method.indexOf('('); + return length !== -1 ? method.substr(length + 1, method.length - 1 - (length + 1)) : ""; +}; + +/// @param json abi for contract +/// @returns input parser object for given json abi +var inputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + var displayName = methodDisplayName(method.name); + var typeName = methodTypeName(method.name); + + var impl = function () { + var params = Array.prototype.slice.call(arguments); + return toAbiInput(json, method.name, params); + }; + + if (parser[displayName] === undefined) { + parser[displayName] = impl; + } + + parser[displayName][typeName] = impl; + }); + + return parser; +}; + +/// @param json abi for contract +/// @returns output parser for given json abi +var outputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + + var displayName = methodDisplayName(method.name); + var typeName = methodTypeName(method.name); + + var impl = function (output) { + return fromAbiOutput(json, method.name, output); + }; + + if (parser[displayName] === undefined) { + parser[displayName] = impl; + } + + parser[displayName][typeName] = impl; + }); + + return parser; +}; + +/// @param method name for which we want to get method signature +/// @returns (promise) contract method signature for method with given name +var methodSignature = function (name) { + return web3.sha3(web3.fromAscii(name)).slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2); +}; + +module.exports = { + inputParser: inputParser, + outputParser: outputParser, + methodSignature: methodSignature, + methodDisplayName: methodDisplayName, + methodTypeName: methodTypeName, + getMethodWithName: getMethodWithName +}; + diff --git a/cmd/mist/assets/ext/ethereum.js/lib/contract.js b/cmd/mist/assets/ext/ethereum.js/lib/contract.js new file mode 100644 index 000000000..e71734d0b --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/contract.js @@ -0,0 +1,145 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file contract.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line +var abi = require('./abi'); + +/** + * This method should be called when we want to call / transact some solidity method from javascript + * it returns an object which has same methods available as solidity contract description + * usage example: + * + * var abi = [{ + * name: 'myMethod', + * inputs: [{ name: 'a', type: 'string' }], + * outputs: [{name: 'd', type: 'string' }] + * }]; // contract abi + * + * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object + * + * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default) + * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit) + * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact + * + * @param address - address of the contract, which should be called + * @param desc - abi json description of the contract, which is being created + * @returns contract object + */ + +var contract = function (address, desc) { + + desc.forEach(function (method) { + // workaround for invalid assumption that method.name is the full anonymous prototype of the method. + // it's not. it's just the name. the rest of the code assumes it's actually the anonymous + // prototype, so we make it so as a workaround. + if (method.name.indexOf('(') === -1) { + var displayName = method.name; + var typeName = method.inputs.map(function(i){return i.type; }).join(); + method.name = displayName + '(' + typeName + ')'; + } + }); + + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var result = {}; + + result.call = function (options) { + result._isTransact = false; + result._options = options; + return result; + }; + + result.transact = function (options) { + result._isTransact = true; + result._options = options; + return result; + }; + + result._options = {}; + ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) { + result[p] = function (v) { + result._options[p] = v; + return result; + }; + }); + + + desc.forEach(function (method) { + + var displayName = abi.methodDisplayName(method.name); + var typeName = abi.methodTypeName(method.name); + + var impl = function () { + var params = Array.prototype.slice.call(arguments); + var signature = abi.methodSignature(method.name); + var parsed = inputParser[displayName][typeName].apply(null, params); + + var options = result._options || {}; + options.to = address; + options.data = signature + parsed; + + var isTransact = result._isTransact === true || (result._isTransact !== false && !method.constant); + var collapse = options.collapse !== false; + + // reset + result._options = {}; + result._isTransact = null; + + if (isTransact) { + // it's used byt natspec.js + // TODO: figure out better way to solve this + web3._currentContractAbi = desc; + web3._currentContractAddress = address; + web3._currentContractMethodName = method.name; + web3._currentContractMethodParams = params; + + // transactions do not have any output, cause we do not know, when they will be processed + web3.eth.transact(options); + return; + } + + var output = web3.eth.call(options); + var ret = outputParser[displayName][typeName](output); + if (collapse) + { + if (ret.length === 1) + ret = ret[0]; + else if (ret.length === 0) + ret = null; + } + return ret; + }; + + if (result[displayName] === undefined) { + result[displayName] = impl; + } + + result[displayName][typeName] = impl; + + }); + + return result; +}; + +module.exports = contract; + diff --git a/cmd/mist/assets/ext/ethereum.js/lib/filter.js b/cmd/mist/assets/ext/ethereum.js/lib/filter.js new file mode 100644 index 000000000..d93064b58 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/filter.js @@ -0,0 +1,73 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file filter.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line + +/// should be used when we want to watch something +/// it's using inner polling mechanism and is notified about changes +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + this.id = impl.newFilter(options); + web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); +}; + +/// alias for changed* +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +/// gets called when there is new eth/shh message +Filter.prototype.changed = function(callback) { + this.callbacks.push(callback); +}; + +/// trigger calling new message from people +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]); + } + } +}; + +/// should be called to uninstall current filter +Filter.prototype.uninstall = function() { + this.impl.uninstallFilter(this.id); + web3.provider.stopPolling(this.id); +}; + +/// should be called to manually trigger getting latest messages from the client +Filter.prototype.messages = function() { + return this.impl.getMessages(this.id); +}; + +/// alias for messages +Filter.prototype.logs = function () { + return this.messages(); +}; + +module.exports = Filter; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/httpsync.js b/cmd/mist/assets/ext/ethereum.js/lib/httpsync.js new file mode 100644 index 000000000..a638cfe94 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/httpsync.js @@ -0,0 +1,70 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file httpsync.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * @date 2014 + */ + +if (process.env.NODE_ENV !== 'build') { + var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +} + +var HttpSyncProvider = function (host) { + this.handlers = []; + 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 request = new XMLHttpRequest(); + request.open('POST', this.host, false); + request.send(JSON.stringify(data)); + + // check request.status + return request.responseText; +}; + +module.exports = HttpSyncProvider; + diff --git a/cmd/mist/assets/ext/ethereum.js/lib/local.js b/cmd/mist/assets/ext/ethereum.js/lib/local.js new file mode 100644 index 000000000..30cd14df2 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/local.js @@ -0,0 +1,18 @@ +var addressName = {"0x12378912345789": "Gav", "0x57835893478594739854": "Jeff"}; +var nameAddress = {}; + +for (var prop in addressName) { + if (addressName.hasOwnProperty(prop)) { + nameAddress[addressName[prop]] = prop; + } +} + +var local = { + addressBook:{ + byName: addressName, + byAddress: nameAddress + } +}; + +if (typeof(module) !== "undefined") + module.exports = local; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/providermanager.js b/cmd/mist/assets/ext/ethereum.js/lib/providermanager.js new file mode 100644 index 000000000..25cd14288 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/providermanager.js @@ -0,0 +1,110 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file providermanager.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +var web3 = require('./web3'); // jshint ignore:line + +/** + * Provider manager object prototype + * It's responsible for passing messages to providers + * If no provider is set it's responsible for queuing requests + * It's also responsible for polling the ethereum node for incoming messages + * Default poll timeout is 12 seconds + * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, + * and provider manager polling mechanism is not used + */ +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); + + // dont call the callback if result is not an array, or empty one + if (result.error || !(result.result instanceof Array) || result.result.length === 0) { + return; + } + + data.callback(result.result); + }); + } + setTimeout(poll, 1000); + }; + poll(); +}; + +/// sends outgoing requests +ProviderManager.prototype.send = function(data) { + + data.args = data.args || []; + data._id = this.id++; + + 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); + + if (result.error) { + console.log(result.error); + return null; + } + + return result.result; +}; + +/// setups provider, which will be used for sending messages +ProviderManager.prototype.set = function(provider) { + this.provider = provider; +}; + +/// this method is only used, when we do not have native qt bindings and have to do polling on our own +/// should be callled, on start watching for eth/shh changes +ProviderManager.prototype.startPolling = function (data, pollId, callback) { + this.polls.push({data: data, id: pollId, callback: callback}); +}; + +/// should be called to stop polling for certain watch changes +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +module.exports = ProviderManager; + diff --git a/cmd/mist/assets/ext/ethereum.js/lib/qtsync.js b/cmd/mist/assets/ext/ethereum.js/lib/qtsync.js new file mode 100644 index 000000000..a287a7172 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/qtsync.js @@ -0,0 +1,32 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file qtsync.js + * @authors: + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * @date 2014 + */ + +var QtSyncProvider = function () { +}; + +QtSyncProvider.prototype.send = function (payload) { + return navigator.qt.callMethod(JSON.stringify(payload)); +}; + +module.exports = QtSyncProvider; + diff --git a/cmd/mist/assets/ext/ethereum.js/lib/web3.js b/cmd/mist/assets/ext/ethereum.js/lib/web3.js new file mode 100644 index 000000000..7b8bbd28a --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/web3.js @@ -0,0 +1,327 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file web3.js + * @authors: + * Jeffrey Wilcke <jeff@ethdev.com> + * Marek Kotewicz <marek@ethdev.com> + * Marian Oancea <marian@ethdev.com> + * Gav Wood <g@ethdev.com> + * @date 2014 + */ + +if (process.env.NODE_ENV !== 'build') { + var BigNumber = require('bignumber.js'); +} + +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 [ + { name: 'sha3', call: 'web3_sha3' } + ]; +}; + +/// @returns an array of objects describing web3.eth api methods +var ethMethods = function () { + var blockCall = function (args) { + return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; + }; + + var transactionCall = function (args) { + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + }; + + var uncleCall = function (args) { + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + }; + + var methods = [ + { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'storageAt', call: 'eth_storageAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, + { name: 'block', call: blockCall }, + { name: 'transaction', call: transactionCall }, + { name: 'uncle', call: uncleCall }, + { name: 'compilers', call: 'eth_compilers' }, + { name: 'flush', call: 'eth_flush' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'serpent', call: 'eth_serpent' }, + { name: 'logs', call: 'eth_logs' } + ]; + return methods; +}; + +/// @returns an array of objects describing web3.eth api properties +var ethProperties = function () { + return [ + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} + ]; +}; + +/// @returns an array of objects describing web3.db api methods +var dbMethods = function () { + return [ + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_getString' } + ]; +}; + +/// @returns an array of objects describing web3.shh api methods +var shhMethods = function () { + return [ + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } + ]; +}; + +/// @returns an array of objects describing web3.eth.watch api methods +var ethWatchMethods = function () { + var newFilter = function (args) { + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; + }; + + return [ + { name: 'newFilter', call: newFilter }, + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_filterLogs' } + ]; +}; + +/// @returns an array of objects describing web3.shh.watch api methods +var shhWatchMethods = function () { + return [ + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessages', call: 'shh_getMessages' } + ]; +}; + +/// creates methods in a given object based on method description on input +/// setups api calls for these methods +var setupMethods = function (obj, methods) { + methods.forEach(function (method) { + obj[method.name] = function () { + 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 + }); + }; + }); +}; + +/// creates properties in a given object based on properties description on input +/// setups api calls for these properties +var setupProperties = function (obj, properties) { + properties.forEach(function (property) { + var proto = {}; + proto.get = function () { + return web3.provider.send({ + call: property.getter + }); + }; + + if (property.setter) { + proto.set = function (val) { + return web3.provider.send({ + call: property.setter, + args: [val] + }); + }; + } + Object.defineProperty(obj, property.name, proto); + }); +}; + +/// setups web3 object, and it's in-browser executed methods +var web3 = { + _callbacks: {}, + _events: {}, + providers: {}, + + toHex: function(str) { + var hex = ""; + for(var i = 0; i < str.length; i++) { + var n = str.charCodeAt(i).toString(16); + hex += n.length < 2 ? '0' + n : n; + } + + return hex; + }, + + /// @returns ascii string representation of hex value prefixed with 0x + toAscii: function(hex) { + // Find termination + var str = ""; + var i = 0, l = hex.length; + if (hex.substring(0, 2) === '0x') + i = 2; + for(; i < l; i+=2) { + var code = parseInt(hex.substr(i, 2), 16); + if(code === 0) { + break; + } + + str += String.fromCharCode(code); + } + + return str; + }, + + /// @returns hex representation (prefixed by 0x) of ascii string + fromAscii: function(str, pad) { + pad = pad === undefined ? 0 : pad; + var hex = this.toHex(str); + while(hex.length < pad*2) + hex += "00"; + return "0x" + hex; + }, + + /// @returns decimal representaton of hex value prefixed by 0x + toDecimal: function (val) { + // remove 0x and place 0, if it's required + val = val.length > 2 ? val.substring(2) : "0"; + return (new BigNumber(val, 16).toString(10)); + }, + + /// @returns hex representation (prefixed by 0x) of decimal value + fromDecimal: function (val) { + return "0x" + (new BigNumber(val).toString(16)); + }, + + /// 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]; + }, + + /// eth object prototype + eth: { + contractFromAbi: function (abi) { + return function(addr) { + // Default to address of Config. TODO: rremove prior to genesis. + addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b'; + var ret = web3.eth.contract(addr, abi); + ret.address = addr; + return ret; + }; + }, + watch: function (params) { + return new web3.filter(params, ethWatch); + } + }, + + /// db object prototype + db: {}, + + /// shh object prototype + shh: { + watch: function (params) { + return new web3.filter(params, shhWatch); + } + }, + + /// @returns true if provider is installed + haveProvider: function() { + return !!web3.provider.provider; + } +}; + +/// setups all api methods +setupMethods(web3, web3Methods()); +setupMethods(web3.eth, ethMethods()); +setupProperties(web3.eth, ethProperties()); +setupMethods(web3.db, dbMethods()); +setupMethods(web3.shh, shhMethods()); + +var ethWatch = { + changed: 'eth_changed' +}; + +setupMethods(ethWatch, ethWatchMethods()); + +var shhWatch = { + changed: 'shh_changed' +}; + +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; + diff --git a/cmd/mist/assets/ext/ethereum.js/package.json b/cmd/mist/assets/ext/ethereum.js/package.json new file mode 100644 index 000000000..7fc20a667 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/package.json @@ -0,0 +1,69 @@ +{ + "name": "ethereum.js", + "namespace": "ethereum", + "version": "0.0.10", + "description": "Ethereum Compatible JavaScript API", + "main": "./index.js", + "directories": { + "lib": "./lib" + }, + "dependencies": { + "ws": "*", + "xmlhttprequest": "*", + "bignumber.js": ">=2.0.0" + }, + "devDependencies": { + "bower": ">=1.3.0", + "browserify": ">=6.0", + "del": ">=0.1.1", + "envify": "^3.0.0", + "exorcist": "^0.1.6", + "gulp": ">=3.4.0", + "gulp-jshint": ">=1.5.0", + "gulp-rename": ">=1.2.0", + "gulp-uglify": ">=1.0.0", + "jshint": ">=2.5.0", + "uglifyify": "^2.6.0", + "unreachable-branch-transform": "^0.1.0", + "vinyl-source-stream": "^1.0.0", + "mocha": ">=2.1.0" + }, + "scripts": { + "build": "gulp", + "watch": "gulp watch", + "lint": "gulp lint", + "test": "mocha" + }, + "repository": { + "type": "git", + "url": "https://github.com/ethereum/ethereum.js.git" + }, + "homepage": "https://github.com/ethereum/ethereum.js", + "bugs": { + "url": "https://github.com/ethereum/ethereum.js/issues" + }, + "keywords": [ + "ethereum", + "javascript", + "API" + ], + "author": "ethdev.com", + "authors": [ + { + "name": "Jeffery Wilcke", + "email": "jeff@ethdev.com", + "url": "https://github.com/obscuren" + }, + { + "name": "Marek Kotewicz", + "email": "marek@ethdev.com", + "url": "https://github.com/debris" + }, + { + "name": "Marian Oancea", + "email": "marian@ethdev.com", + "url": "https://github.com/cubedro" + } + ], + "license": "LGPL-3.0" +} diff --git a/cmd/mist/assets/ext/ethereum.js/test/abi.parsers.js b/cmd/mist/assets/ext/ethereum.js/test/abi.parsers.js new file mode 100644 index 000000000..b7a05cea3 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/abi.parsers.js @@ -0,0 +1,860 @@ +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", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] +}]; + +describe('abi', function() { + describe('inputParser', function() { + it('should parse input uint', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + + }); + + it('should parse input uint128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + + }); + + it('should parse input uint256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + + }); + + it('should parse input int', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + }); + + it('should parse input int128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + + }); + + it('should parse input int256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + + }); + + it('should parse input bool', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(true), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(false), "0000000000000000000000000000000000000000000000000000000000000000"); + + }); + + it('should parse input hash', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input hash256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + + it('should parse input hash160', function() { + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash160" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + }); + + it('should parse input address', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "address" } + ]; + + // when + var parser = abi.inputParser(d) + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input string', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "string" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test('hello'), + "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" + ); + assert.equal( + parser.test('world'), + "0000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000" + ); + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld(int)'; + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.helloworld['int'](1), "0000000000000000000000000000000000000000000000000000000000000001"); + + }); + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] + }]; + + // when + var parser = abi.inputParser(d); + + //then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal( + parser.test2('hello'), + "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" + ); + + }); + + it('should parse input array of ints', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int[]" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test([5, 6]), + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006" + ); + }); + + it('should parse input real', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'real' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); + + }); + + it('should parse input ureal', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'ureal' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + + }); + + }); + + 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", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + 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/cmd/mist/assets/ext/ethereum.js/test/db.methods.js b/cmd/mist/assets/ext/ethereum.js/test/db.methods.js new file mode 100644 index 000000000..8f8f5409f --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/db.methods.js @@ -0,0 +1,14 @@ + +var assert = require('assert'); +var web3 = require('../index.js'); +var u = require('./utils.js'); + +describe('web3', function() { + describe('db', function() { + u.methodExists(web3.db, 'put'); + u.methodExists(web3.db, 'get'); + u.methodExists(web3.db, 'putString'); + u.methodExists(web3.db, 'getString'); + }); +}); + diff --git a/cmd/mist/assets/ext/ethereum.js/test/eth.methods.js b/cmd/mist/assets/ext/ethereum.js/test/eth.methods.js new file mode 100644 index 000000000..7a031c4c8 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/eth.methods.js @@ -0,0 +1,34 @@ +var assert = require('assert'); +var web3 = require('../index.js'); +var u = require('./utils.js'); + +describe('web3', function() { + describe('eth', function() { + u.methodExists(web3.eth, 'balanceAt'); + u.methodExists(web3.eth, 'stateAt'); + u.methodExists(web3.eth, 'storageAt'); + u.methodExists(web3.eth, 'countAt'); + u.methodExists(web3.eth, 'codeAt'); + u.methodExists(web3.eth, 'transact'); + u.methodExists(web3.eth, 'call'); + u.methodExists(web3.eth, 'block'); + u.methodExists(web3.eth, 'transaction'); + u.methodExists(web3.eth, 'uncle'); + u.methodExists(web3.eth, 'compilers'); + u.methodExists(web3.eth, 'lll'); + u.methodExists(web3.eth, 'solidity'); + u.methodExists(web3.eth, 'serpent'); + u.methodExists(web3.eth, 'logs'); + + u.propertyExists(web3.eth, 'coinbase'); + u.propertyExists(web3.eth, 'listening'); + u.propertyExists(web3.eth, 'mining'); + u.propertyExists(web3.eth, 'gasPrice'); + u.propertyExists(web3.eth, 'accounts'); + u.propertyExists(web3.eth, 'peerCount'); + u.propertyExists(web3.eth, 'defaultBlock'); + u.propertyExists(web3.eth, 'number'); + }); +}); + + diff --git a/cmd/mist/assets/ext/ethereum.js/test/mocha.opts b/cmd/mist/assets/ext/ethereum.js/test/mocha.opts new file mode 100644 index 000000000..c4a633d64 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/mocha.opts @@ -0,0 +1,2 @@ +--reporter spec + diff --git a/cmd/mist/assets/ext/ethereum.js/test/shh.methods.js b/cmd/mist/assets/ext/ethereum.js/test/shh.methods.js new file mode 100644 index 000000000..fe2dae71d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/shh.methods.js @@ -0,0 +1,14 @@ +var assert = require('assert'); +var web3 = require('../index.js'); +var u = require('./utils.js'); + +describe('web3', function() { + describe('shh', function() { + u.methodExists(web3.shh, 'post'); + u.methodExists(web3.shh, 'newIdentity'); + u.methodExists(web3.shh, 'haveIdentity'); + u.methodExists(web3.shh, 'newGroup'); + u.methodExists(web3.shh, 'addToGroup'); + }); +}); + diff --git a/cmd/mist/assets/ext/ethereum.js/test/utils.js b/cmd/mist/assets/ext/ethereum.js/test/utils.js new file mode 100644 index 000000000..8a1e9a0b6 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/utils.js @@ -0,0 +1,19 @@ +var assert = require('assert'); + +var methodExists = function (object, method) { + it('should have method ' + method + ' implemented', function() { + assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented'); + }); +}; + +var propertyExists = function (object, property) { + it('should have property ' + property + ' implemented', function() { + assert.notEqual('undefined', typeof object[property], 'property ' + property + ' is not implemented'); + }); +}; + +module.exports = { + methodExists: methodExists, + propertyExists: propertyExists +}; + diff --git a/cmd/mist/assets/ext/ethereum.js/test/web3.methods.js b/cmd/mist/assets/ext/ethereum.js/test/web3.methods.js new file mode 100644 index 000000000..d08495dd9 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/test/web3.methods.js @@ -0,0 +1,10 @@ +var assert = require('assert'); +var web3 = require('../index.js'); +var u = require('./utils.js'); + +describe('web3', function() { + u.methodExists(web3, 'sha3'); + u.methodExists(web3, 'toAscii'); + u.methodExists(web3, 'fromAscii'); +}); + diff --git a/cmd/mist/assets/ext/home.html b/cmd/mist/assets/ext/home.html deleted file mode 100644 index a524e8403..000000000 --- a/cmd/mist/assets/ext/home.html +++ /dev/null @@ -1,22 +0,0 @@ -<!doctype> -<html> -<head> -<title>Ethereum</title> - -<style type="text/css"> -h1 { - text-align: center; - font-family: Courier; - font-size: 50pt; -} -</style> -</head> - -<body> -<h1>... Ethereum ...</h1> -<ul> - <li><a href="http://std.eth">std::Service</a></li> -</ul> -</body> -</html> - diff --git a/cmd/mist/assets/ext/html_messaging.js b/cmd/mist/assets/ext/html_messaging.js deleted file mode 100644 index f58eb7c29..000000000 --- a/cmd/mist/assets/ext/html_messaging.js +++ /dev/null @@ -1,481 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -// The magic return variable. The magic return variable will be set during the execution of the QML call. -(function(window) { - var Promise = window.Promise; - if(typeof(Promise) === "undefined") { - var Promise = Q.Promise; - } - - function isPromise(o) { - return typeof o === "object" && o.then - } - - window.eth = { - _callbacks: {}, - _events: {}, - prototype: Object(), - - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, - - toAscii: function(hex) { - // Find termination - var str = ""; - var i = 0, l = hex.length; - for(; i < l; i+=2) { - var code = hex.charCodeAt(i) - if(code == 0) { - break; - } - - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - - return str; - }, - - fromAscii: function(str, pad) { - if(pad === undefined) { - pad = 32 - } - - var hex = this.toHex(str); - - while(hex.length < pad*2) - hex += "00"; - - return hex - }, - - block: function(numberOrHash) { - return new Promise(function(resolve, reject) { - var func; - if(typeof numberOrHash == "string") { - func = "getBlockByHash"; - } else { - func = "getBlockByNumber"; - } - - postData({call: func, args: [numberOrHash]}, function(block) { - if(block) - resolve(block); - else - reject("not found"); - - }); - }); - }, - - transact: function(params) { - if(params === undefined) { - params = {}; - } - - if(params.endowment !== undefined) - params.value = params.endowment; - if(params.code !== undefined) - params.data = params.code; - - - var promises = [] - if(isPromise(params.to)) { - promises.push(params.to.then(function(_to) { params.to = _to; })); - } - if(isPromise(params.from)) { - promises.push(params.from.then(function(_from) { params.from = _from; })); - } - - if(typeof params.data !== "object" || isPromise(params.data)) { - params.data = [params.data] - } - - var data = params.data; - for(var i = 0; i < params.data.length; i++) { - if(isPromise(params.data[i])) { - var promise = params.data[i]; - var _i = i; - promises.push(promise.then(function(_arg) { params.data[_i] = _arg; })); - } - } - - // Make sure everything is string - var fields = ["value", "gas", "gasPrice"]; - for(var i = 0; i < fields.length; i++) { - if(params[fields[i]] === undefined) { - params[fields[i]] = ""; - } - params[fields[i]] = params[fields[i]].toString(); - } - - // Load promises then call the last "transact". - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - params.data = params.data.join(""); - postData({call: "transact", args: params}, function(data) { - if(data[1]) - reject(data[0]); - else - resolve(data[0]); - }); - }); - }) - }, - - compile: function(code) { - return new Promise(function(resolve, reject) { - postData({call: "compile", args: [code]}, function(data) { - if(data[1]) - reject(data[0]); - else - resolve(data[0]); - }); - }); - }, - - balanceAt: function(address) { - var promises = []; - - if(isPromise(address)) { - promises.push(address.then(function(_address) { address = _address; })); - } - - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "getBalanceAt", args: [address]}, function(balance) { - resolve(balance); - }); - }); - }); - }, - - countAt: function(address) { - var promises = []; - - if(isPromise(address)) { - promises.push(address.then(function(_address) { address = _address; })); - } - - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "getCountAt", args: [address]}, function(count) { - resolve(count); - }); - }); - }); - }, - - codeAt: function(address) { - var promises = []; - - if(isPromise(address)) { - promises.push(address.then(function(_address) { address = _address; })); - } - - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "getCodeAt", args: [address]}, function(code) { - resolve(code); - }); - }); - }); - }, - - storageAt: function(address, storageAddress) { - var promises = []; - - if(isPromise(address)) { - promises.push(address.then(function(_address) { address = _address; })); - } - - if(isPromise(storageAddress)) { - promises.push(storageAddress.then(function(_sa) { storageAddress = _sa; })); - } - - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "getStorageAt", args: [address, storageAddress]}, function(entry) { - resolve(entry); - }); - }); - }); - }, - - stateAt: function(address, storageAddress) { - return this.storageAt(address, storageAddress); - }, - - call: function(params) { - if(params === undefined) { - params = {}; - } - - if(params.endowment !== undefined) - params.value = params.endowment; - if(params.code !== undefined) - params.data = params.code; - - - var promises = [] - if(isPromise(params.to)) { - promises.push(params.to.then(function(_to) { params.to = _to; })); - } - if(isPromise(params.from)) { - promises.push(params.from.then(function(_from) { params.from = _from; })); - } - - if(isPromise(params.data)) { - promises.push(params.data.then(function(_code) { params.data = _code; })); - } else { - if(typeof params.data === "object") { - data = ""; - for(var i = 0; i < params.data.length; i++) { - data += params.data[i] - } - } else { - data = params.data; - } - } - - // Make sure everything is string - var fields = ["value", "gas", "gasPrice"]; - for(var i = 0; i < fields.length; i++) { - if(params[fields[i]] === undefined) { - params[fields[i]] = ""; - } - params[fields[i]] = params[fields[i]].toString(); - } - - // Load promises then call the last "transact". - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "call", args: params}, function(data) { - if(data[1]) - reject(data[0]); - else - resolve(data[0]); - }); - }); - }) - }, - - watch: function(params) { - return new Filter(params); - }, - - secretToAddress: function(key) { - var promises = []; - if(isPromise(key)) { - promises.push(key.then(function(_key) { key = _key; })); - } - - return Q.all(promises).then(function() { - return new Promise(function(resolve, reject) { - postData({call: "getSecretToAddress", args: [key]}, function(address) { - resolve(address); - }); - }); - }); - }, - - on: function(event, cb) { - if(eth._events[event] === undefined) { - eth._events[event] = []; - } - - eth._events[event].push(cb); - - return this - }, - - off: function(event, cb) { - if(eth._events[event] !== undefined) { - var callbacks = eth._events[event]; - for(var i = 0; i < callbacks.length; i++) { - if(callbacks[i] === cb) { - delete callbacks[i]; - } - } - } - - return this - }, - - trigger: function(event, data) { - var callbacks = eth._events[event]; - if(callbacks !== undefined) { - for(var i = 0; i < callbacks.length; i++) { - // Figure out whether the returned data was an array - // array means multiple return arguments (multiple params) - if(data instanceof Array) { - callbacks[i].apply(this, data); - } else { - callbacks[i].call(this, data); - } - } - } - }, - }; - - // Eth object properties - Object.defineProperty(eth, "key", { - get: function() { - return new Promise(function(resolve, reject) { - postData({call: "getKey"}, function(k) { - resolve(k); - }); - }); - }, - }); - - Object.defineProperty(eth, "gasPrice", { - get: function() { - return "10000000000000" - } - }); - - Object.defineProperty(eth, "coinbase", { - get: function() { - return new Promise(function(resolve, reject) { - postData({call: "getCoinBase"}, function(coinbase) { - resolve(coinbase); - }); - }); - }, - }); - - Object.defineProperty(eth, "listening", { - get: function() { - return new Promise(function(resolve, reject) { - postData({call: "getIsListening"}, function(listening) { - resolve(listening); - }); - }); - }, - }); - - - Object.defineProperty(eth, "mining", { - get: function() { - return new Promise(function(resolve, reject) { - postData({call: "getIsMining"}, function(mining) { - resolve(mining); - }); - }); - }, - }); - - Object.defineProperty(eth, "peerCount", { - get: function() { - return new Promise(function(resolve, reject) { - postData({call: "getPeerCount"}, function(peerCount) { - resolve(peerCount); - }); - }); - }, - }); - - var filters = []; - var Filter = function(options) { - filters.push(this); - - this.callbacks = []; - this.options = options; - - var call; - if(options === "chain") { - call = "newFilterString" - } else if(typeof options === "object") { - call = "newFilter" - } - - var self = this; // Cheaper than binding - this.promise = new Promise(function(resolve, reject) { - postData({call: call, args: [options]}, function(id) { - self.id = id; - - resolve(id); - }); - }); - }; - - Filter.prototype.changed = function(callback) { - var self = this; - this.promise.then(function(id) { - self.callbacks.push(callback); - }); - }; - - Filter.prototype.trigger = function(messages, id) { - if(id == this.id) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } - } - }; - - Filter.prototype.uninstall = function() { - this.promise.then(function(id) { - postData({call: "uninstallFilter", args:[id]}); - }); - }; - - Filter.prototype.messages = function() { - var self=this; - return Q.all([this.promise]).then(function() { - var id = self.id - return new Promise(function(resolve, reject) { - postData({call: "getMessages", args: [id]}, function(messages) { - resolve(messages); - }); - }); - }); - }; - - // Register to the messages callback. "messages" will be emitted when new messages - // from the client have been created. - eth.on("messages", function(messages, id) { - for(var i = 0; i < filters.length; i++) { - filters[i].trigger(messages, id); - } - }); - - - var g_seed = 1; - function postData(data, cb) { - data._seed = g_seed; - if(cb) { - eth._callbacks[data._seed] = cb; - } - - if(data.args === undefined) { - data.args = []; - } - - g_seed++; - - window._messagingAdapter.call(this, JSON.stringify(data)) - } -})(this); diff --git a/cmd/mist/assets/ext/q.js b/cmd/mist/assets/ext/q.js deleted file mode 100644 index 23c4245ee..000000000 --- a/cmd/mist/assets/ext/q.js +++ /dev/null @@ -1,1909 +0,0 @@ -// vim:ts=4:sts=4:sw=4: -/*! - * - * Copyright 2009-2012 Kris Kowal under the terms of the MIT - * license found at http://github.com/kriskowal/q/raw/master/LICENSE - * - * With parts by Tyler Close - * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found - * at http://www.opensource.org/licenses/mit-license.html - * Forked at ref_send.js version: 2009-05-11 - * - * With parts by Mark Miller - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -(function (definition) { - // Turn off strict mode for this function so we can assign to global.Q - /* jshint strict: false */ - - // This file will function properly as a <script> tag, or a module - // using CommonJS and NodeJS or RequireJS module formats. In - // Common/Node/RequireJS, the module exports the Q API and when - // executed as a simple <script>, it creates a Q global instead. - - // Montage Require - if (typeof bootstrap === "function") { - bootstrap("promise", definition); - - // CommonJS - } else if (typeof exports === "object" && typeof module === "object") { - module.exports = definition(); - - // RequireJS - } else if (typeof define === "function" && define.amd) { - define(definition); - - // SES (Secure EcmaScript) - } else if (typeof ses !== "undefined") { - if (!ses.ok()) { - return; - } else { - ses.makeQ = definition; - } - - // <script> - } else { - Q = definition(); - } - -})(function () { -"use strict"; - -var hasStacks = false; -try { - throw new Error(); -} catch (e) { - hasStacks = !!e.stack; -} - -// All code after this point will be filtered from stack traces reported -// by Q. -var qStartingLine = captureLine(); -var qFileName; - -// shims - -// used for fallback in "allResolved" -var noop = function () {}; - -// Use the fastest possible means to execute a task in a future turn -// of the event loop. -var nextTick =(function () { - // linked list of tasks (single, with head node) - var head = {task: void 0, next: null}; - var tail = head; - var flushing = false; - var requestTick = void 0; - var isNodeJS = false; - - function flush() { - /* jshint loopfunc: true */ - - while (head.next) { - head = head.next; - var task = head.task; - head.task = void 0; - var domain = head.domain; - - if (domain) { - head.domain = void 0; - domain.enter(); - } - - try { - task(); - - } catch (e) { - if (isNodeJS) { - // In node, uncaught exceptions are considered fatal errors. - // Re-throw them synchronously to interrupt flushing! - - // Ensure continuation if the uncaught exception is suppressed - // listening "uncaughtException" events (as domains does). - // Continue in next event to avoid tick recursion. - if (domain) { - domain.exit(); - } - setTimeout(flush, 0); - if (domain) { - domain.enter(); - } - - throw e; - - } else { - // In browsers, uncaught exceptions are not fatal. - // Re-throw them asynchronously to avoid slow-downs. - setTimeout(function() { - throw e; - }, 0); - } - } - - if (domain) { - domain.exit(); - } - } - - flushing = false; - } - - nextTick = function (task) { - tail = tail.next = { - task: task, - domain: isNodeJS && process.domain, - next: null - }; - - if (!flushing) { - flushing = true; - requestTick(); - } - }; - - if (typeof process !== "undefined" && process.nextTick) { - // Node.js before 0.9. Note that some fake-Node environments, like the - // Mocha test runner, introduce a `process` global without a `nextTick`. - isNodeJS = true; - - requestTick = function () { - process.nextTick(flush); - }; - - } else if (typeof setImmediate === "function") { - // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate - if (typeof window !== "undefined") { - requestTick = setImmediate.bind(window, flush); - } else { - requestTick = function () { - setImmediate(flush); - }; - } - - } else if (typeof MessageChannel !== "undefined") { - // modern browsers - // http://www.nonblocking.io/2011/06/windownexttick.html - var channel = new MessageChannel(); - // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create - // working message ports the first time a page loads. - channel.port1.onmessage = function () { - requestTick = requestPortTick; - channel.port1.onmessage = flush; - flush(); - }; - var requestPortTick = function () { - // Opera requires us to provide a message payload, regardless of - // whether we use it. - channel.port2.postMessage(0); - }; - requestTick = function () { - setTimeout(flush, 0); - requestPortTick(); - }; - - } else { - // old browsers - requestTick = function () { - setTimeout(flush, 0); - }; - } - - return nextTick; -})(); - -// Attempt to make generics safe in the face of downstream -// modifications. -// There is no situation where this is necessary. -// If you need a security guarantee, these primordials need to be -// deeply frozen anyway, and if you don’t need a security guarantee, -// this is just plain paranoid. -// However, this **might** have the nice side-effect of reducing the size of -// the minified code by reducing x.call() to merely x() -// See Mark Miller’s explanation of what this does. -// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming -var call = Function.call; -function uncurryThis(f) { - return function () { - return call.apply(f, arguments); - }; -} -// This is equivalent, but slower: -// uncurryThis = Function_bind.bind(Function_bind.call); -// http://jsperf.com/uncurrythis - -var array_slice = uncurryThis(Array.prototype.slice); - -var array_reduce = uncurryThis( - Array.prototype.reduce || function (callback, basis) { - var index = 0, - length = this.length; - // concerning the initial value, if one is not provided - if (arguments.length === 1) { - // seek to the first value in the array, accounting - // for the possibility that is is a sparse array - do { - if (index in this) { - basis = this[index++]; - break; - } - if (++index >= length) { - throw new TypeError(); - } - } while (1); - } - // reduce - for (; index < length; index++) { - // account for the possibility that the array is sparse - if (index in this) { - basis = callback(basis, this[index], index); - } - } - return basis; - } -); - -var array_indexOf = uncurryThis( - Array.prototype.indexOf || function (value) { - // not a very good shim, but good enough for our one use of it - for (var i = 0; i < this.length; i++) { - if (this[i] === value) { - return i; - } - } - return -1; - } -); - -var array_map = uncurryThis( - Array.prototype.map || function (callback, thisp) { - var self = this; - var collect = []; - array_reduce(self, function (undefined, value, index) { - collect.push(callback.call(thisp, value, index, self)); - }, void 0); - return collect; - } -); - -var object_create = Object.create || function (prototype) { - function Type() { } - Type.prototype = prototype; - return new Type(); -}; - -var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty); - -var object_keys = Object.keys || function (object) { - var keys = []; - for (var key in object) { - if (object_hasOwnProperty(object, key)) { - keys.push(key); - } - } - return keys; -}; - -var object_toString = uncurryThis(Object.prototype.toString); - -function isObject(value) { - return value === Object(value); -} - -// generator related shims - -// FIXME: Remove this function once ES6 generators are in SpiderMonkey. -function isStopIteration(exception) { - return ( - object_toString(exception) === "[object StopIteration]" || - exception instanceof QReturnValue - ); -} - -// FIXME: Remove this helper and Q.return once ES6 generators are in -// SpiderMonkey. -var QReturnValue; -if (typeof ReturnValue !== "undefined") { - QReturnValue = ReturnValue; -} else { - QReturnValue = function (value) { - this.value = value; - }; -} - -// long stack traces - -var STACK_JUMP_SEPARATOR = "From previous event:"; - -function makeStackTraceLong(error, promise) { - // If possible, transform the error stack trace by removing Node and Q - // cruft, then concatenating with the stack trace of `promise`. See #57. - if (hasStacks && - promise.stack && - typeof error === "object" && - error !== null && - error.stack && - error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1 - ) { - var stacks = []; - for (var p = promise; !!p; p = p.source) { - if (p.stack) { - stacks.unshift(p.stack); - } - } - stacks.unshift(error.stack); - - var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n"); - error.stack = filterStackString(concatedStacks); - } -} - -function filterStackString(stackString) { - var lines = stackString.split("\n"); - var desiredLines = []; - for (var i = 0; i < lines.length; ++i) { - var line = lines[i]; - - if (!isInternalFrame(line) && !isNodeFrame(line) && line) { - desiredLines.push(line); - } - } - return desiredLines.join("\n"); -} - -function isNodeFrame(stackLine) { - return stackLine.indexOf("(module.js:") !== -1 || - stackLine.indexOf("(node.js:") !== -1; -} - -function getFileNameAndLineNumber(stackLine) { - // Named functions: "at functionName (filename:lineNumber:columnNumber)" - // In IE10 function name can have spaces ("Anonymous function") O_o - var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine); - if (attempt1) { - return [attempt1[1], Number(attempt1[2])]; - } - - // Anonymous functions: "at filename:lineNumber:columnNumber" - var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine); - if (attempt2) { - return [attempt2[1], Number(attempt2[2])]; - } - - // Firefox style: "function@filename:lineNumber or @filename:lineNumber" - var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine); - if (attempt3) { - return [attempt3[1], Number(attempt3[2])]; - } -} - -function isInternalFrame(stackLine) { - var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine); - - if (!fileNameAndLineNumber) { - return false; - } - - var fileName = fileNameAndLineNumber[0]; - var lineNumber = fileNameAndLineNumber[1]; - - return fileName === qFileName && - lineNumber >= qStartingLine && - lineNumber <= qEndingLine; -} - -// discover own file name and line number range for filtering stack -// traces -function captureLine() { - if (!hasStacks) { - return; - } - - try { - throw new Error(); - } catch (e) { - var lines = e.stack.split("\n"); - var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2]; - var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine); - if (!fileNameAndLineNumber) { - return; - } - - qFileName = fileNameAndLineNumber[0]; - return fileNameAndLineNumber[1]; - } -} - -function deprecate(callback, name, alternative) { - return function () { - if (typeof console !== "undefined" && - typeof console.warn === "function") { - console.warn(name + " is deprecated, use " + alternative + - " instead.", new Error("").stack); - } - return callback.apply(callback, arguments); - }; -} - -// end of shims -// beginning of real work - -/** - * Constructs a promise for an immediate reference, passes promises through, or - * coerces promises from different systems. - * @param value immediate reference or promise - */ -function Q(value) { - // If the object is already a Promise, return it directly. This enables - // the resolve function to both be used to created references from objects, - // but to tolerably coerce non-promises to promises. - if (value instanceof Promise) { - return value; - } - - // assimilate thenables - if (isPromiseAlike(value)) { - return coerce(value); - } else { - return fulfill(value); - } -} -Q.resolve = Q; - -/** - * Performs a task in a future turn of the event loop. - * @param {Function} task - */ -Q.nextTick = nextTick; - -/** - * Controls whether or not long stack traces will be on - */ -Q.longStackSupport = false; - -/** - * Constructs a {promise, resolve, reject} object. - * - * `resolve` is a callback to invoke with a more resolved value for the - * promise. To fulfill the promise, invoke `resolve` with any value that is - * not a thenable. To reject the promise, invoke `resolve` with a rejected - * thenable, or invoke `reject` with the reason directly. To resolve the - * promise to another thenable, thus putting it in the same state, invoke - * `resolve` with that other thenable. - */ -Q.defer = defer; -function defer() { - // if "messages" is an "Array", that indicates that the promise has not yet - // been resolved. If it is "undefined", it has been resolved. Each - // element of the messages array is itself an array of complete arguments to - // forward to the resolved promise. We coerce the resolution value to a - // promise using the `resolve` function because it handles both fully - // non-thenable values and other thenables gracefully. - var messages = [], progressListeners = [], resolvedPromise; - - var deferred = object_create(defer.prototype); - var promise = object_create(Promise.prototype); - - promise.promiseDispatch = function (resolve, op, operands) { - var args = array_slice(arguments); - if (messages) { - messages.push(args); - if (op === "when" && operands[1]) { // progress operand - progressListeners.push(operands[1]); - } - } else { - nextTick(function () { - resolvedPromise.promiseDispatch.apply(resolvedPromise, args); - }); - } - }; - - // XXX deprecated - promise.valueOf = function () { - if (messages) { - return promise; - } - var nearerValue = nearer(resolvedPromise); - if (isPromise(nearerValue)) { - resolvedPromise = nearerValue; // shorten chain - } - return nearerValue; - }; - - promise.inspect = function () { - if (!resolvedPromise) { - return { state: "pending" }; - } - return resolvedPromise.inspect(); - }; - - if (Q.longStackSupport && hasStacks) { - try { - throw new Error(); - } catch (e) { - // NOTE: don't try to use `Error.captureStackTrace` or transfer the - // accessor around; that causes memory leaks as per GH-111. Just - // reify the stack trace as a string ASAP. - // - // At the same time, cut off the first line; it's always just - // "[object Promise]\n", as per the `toString`. - promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1); - } - } - - // NOTE: we do the checks for `resolvedPromise` in each method, instead of - // consolidating them into `become`, since otherwise we'd create new - // promises with the lines `become(whatever(value))`. See e.g. GH-252. - - function become(newPromise) { - resolvedPromise = newPromise; - promise.source = newPromise; - - array_reduce(messages, function (undefined, message) { - nextTick(function () { - newPromise.promiseDispatch.apply(newPromise, message); - }); - }, void 0); - - messages = void 0; - progressListeners = void 0; - } - - deferred.promise = promise; - deferred.resolve = function (value) { - if (resolvedPromise) { - return; - } - - become(Q(value)); - }; - - deferred.fulfill = function (value) { - if (resolvedPromise) { - return; - } - - become(fulfill(value)); - }; - deferred.reject = function (reason) { - if (resolvedPromise) { - return; - } - - become(reject(reason)); - }; - deferred.notify = function (progress) { - if (resolvedPromise) { - return; - } - - array_reduce(progressListeners, function (undefined, progressListener) { - nextTick(function () { - progressListener(progress); - }); - }, void 0); - }; - - return deferred; -} - -/** - * Creates a Node-style callback that will resolve or reject the deferred - * promise. - * @returns a nodeback - */ -defer.prototype.makeNodeResolver = function () { - var self = this; - return function (error, value) { - if (error) { - self.reject(error); - } else if (arguments.length > 2) { - self.resolve(array_slice(arguments, 1)); - } else { - self.resolve(value); - } - }; -}; - -/** - * @param resolver {Function} a function that returns nothing and accepts - * the resolve, reject, and notify functions for a deferred. - * @returns a promise that may be resolved with the given resolve and reject - * functions, or rejected by a thrown exception in resolver - */ -Q.Promise = promise; // ES6 -Q.promise = promise; -function promise(resolver) { - if (typeof resolver !== "function") { - throw new TypeError("resolver must be a function."); - } - var deferred = defer(); - try { - resolver(deferred.resolve, deferred.reject, deferred.notify); - } catch (reason) { - deferred.reject(reason); - } - return deferred.promise; -} - -promise.race = race; // ES6 -promise.all = all; // ES6 -promise.reject = reject; // ES6 -promise.resolve = Q; // ES6 - -// XXX experimental. This method is a way to denote that a local value is -// serializable and should be immediately dispatched to a remote upon request, -// instead of passing a reference. -Q.passByCopy = function (object) { - //freeze(object); - //passByCopies.set(object, true); - return object; -}; - -Promise.prototype.passByCopy = function () { - //freeze(object); - //passByCopies.set(object, true); - return this; -}; - -/** - * If two promises eventually fulfill to the same value, promises that value, - * but otherwise rejects. - * @param x {Any*} - * @param y {Any*} - * @returns {Any*} a promise for x and y if they are the same, but a rejection - * otherwise. - * - */ -Q.join = function (x, y) { - return Q(x).join(y); -}; - -Promise.prototype.join = function (that) { - return Q([this, that]).spread(function (x, y) { - if (x === y) { - // TODO: "===" should be Object.is or equiv - return x; - } else { - throw new Error("Can't join: not the same: " + x + " " + y); - } - }); -}; - -/** - * Returns a promise for the first of an array of promises to become fulfilled. - * @param answers {Array[Any*]} promises to race - * @returns {Any*} the first promise to be fulfilled - */ -Q.race = race; -function race(answerPs) { - return promise(function(resolve, reject) { - // Switch to this once we can assume at least ES5 - // answerPs.forEach(function(answerP) { - // Q(answerP).then(resolve, reject); - // }); - // Use this in the meantime - for (var i = 0, len = answerPs.length; i < len; i++) { - Q(answerPs[i]).then(resolve, reject); - } - }); -} - -Promise.prototype.race = function () { - return this.then(Q.race); -}; - -/** - * Constructs a Promise with a promise descriptor object and optional fallback - * function. The descriptor contains methods like when(rejected), get(name), - * set(name, value), post(name, args), and delete(name), which all - * return either a value, a promise for a value, or a rejection. The fallback - * accepts the operation name, a resolver, and any further arguments that would - * have been forwarded to the appropriate method above had a method been - * provided with the proper name. The API makes no guarantees about the nature - * of the returned object, apart from that it is usable whereever promises are - * bought and sold. - */ -Q.makePromise = Promise; -function Promise(descriptor, fallback, inspect) { - if (fallback === void 0) { - fallback = function (op) { - return reject(new Error( - "Promise does not support operation: " + op - )); - }; - } - if (inspect === void 0) { - inspect = function () { - return {state: "unknown"}; - }; - } - - var promise = object_create(Promise.prototype); - - promise.promiseDispatch = function (resolve, op, args) { - var result; - try { - if (descriptor[op]) { - result = descriptor[op].apply(promise, args); - } else { - result = fallback.call(promise, op, args); - } - } catch (exception) { - result = reject(exception); - } - if (resolve) { - resolve(result); - } - }; - - promise.inspect = inspect; - - // XXX deprecated `valueOf` and `exception` support - if (inspect) { - var inspected = inspect(); - if (inspected.state === "rejected") { - promise.exception = inspected.reason; - } - - promise.valueOf = function () { - var inspected = inspect(); - if (inspected.state === "pending" || - inspected.state === "rejected") { - return promise; - } - return inspected.value; - }; - } - - return promise; -} - -Promise.prototype.toString = function () { - return "[object Promise]"; -}; - -Promise.prototype.then = function (fulfilled, rejected, progressed) { - var self = this; - var deferred = defer(); - var done = false; // ensure the untrusted promise makes at most a - // single call to one of the callbacks - - function _fulfilled(value) { - try { - return typeof fulfilled === "function" ? fulfilled(value) : value; - } catch (exception) { - return reject(exception); - } - } - - function _rejected(exception) { - if (typeof rejected === "function") { - makeStackTraceLong(exception, self); - try { - return rejected(exception); - } catch (newException) { - return reject(newException); - } - } - return reject(exception); - } - - function _progressed(value) { - return typeof progressed === "function" ? progressed(value) : value; - } - - nextTick(function () { - self.promiseDispatch(function (value) { - if (done) { - return; - } - done = true; - - deferred.resolve(_fulfilled(value)); - }, "when", [function (exception) { - if (done) { - return; - } - done = true; - - deferred.resolve(_rejected(exception)); - }]); - }); - - // Progress propagator need to be attached in the current tick. - self.promiseDispatch(void 0, "when", [void 0, function (value) { - var newValue; - var threw = false; - try { - newValue = _progressed(value); - } catch (e) { - threw = true; - if (Q.onerror) { - Q.onerror(e); - } else { - throw e; - } - } - - if (!threw) { - deferred.notify(newValue); - } - }]); - - return deferred.promise; -}; - -/** - * Registers an observer on a promise. - * - * Guarantees: - * - * 1. that fulfilled and rejected will be called only once. - * 2. that either the fulfilled callback or the rejected callback will be - * called, but not both. - * 3. that fulfilled and rejected will not be called in this turn. - * - * @param value promise or immediate reference to observe - * @param fulfilled function to be called with the fulfilled value - * @param rejected function to be called with the rejection exception - * @param progressed function to be called on any progress notifications - * @return promise for the return value from the invoked callback - */ -Q.when = when; -function when(value, fulfilled, rejected, progressed) { - return Q(value).then(fulfilled, rejected, progressed); -} - -Promise.prototype.thenResolve = function (value) { - return this.then(function () { return value; }); -}; - -Q.thenResolve = function (promise, value) { - return Q(promise).thenResolve(value); -}; - -Promise.prototype.thenReject = function (reason) { - return this.then(function () { throw reason; }); -}; - -Q.thenReject = function (promise, reason) { - return Q(promise).thenReject(reason); -}; - -/** - * If an object is not a promise, it is as "near" as possible. - * If a promise is rejected, it is as "near" as possible too. - * If it’s a fulfilled promise, the fulfillment value is nearer. - * If it’s a deferred promise and the deferred has been resolved, the - * resolution is "nearer". - * @param object - * @returns most resolved (nearest) form of the object - */ - -// XXX should we re-do this? -Q.nearer = nearer; -function nearer(value) { - if (isPromise(value)) { - var inspected = value.inspect(); - if (inspected.state === "fulfilled") { - return inspected.value; - } - } - return value; -} - -/** - * @returns whether the given object is a promise. - * Otherwise it is a fulfilled value. - */ -Q.isPromise = isPromise; -function isPromise(object) { - return isObject(object) && - typeof object.promiseDispatch === "function" && - typeof object.inspect === "function"; -} - -Q.isPromiseAlike = isPromiseAlike; -function isPromiseAlike(object) { - return isObject(object) && typeof object.then === "function"; -} - -/** - * @returns whether the given object is a pending promise, meaning not - * fulfilled or rejected. - */ -Q.isPending = isPending; -function isPending(object) { - return isPromise(object) && object.inspect().state === "pending"; -} - -Promise.prototype.isPending = function () { - return this.inspect().state === "pending"; -}; - -/** - * @returns whether the given object is a value or fulfilled - * promise. - */ -Q.isFulfilled = isFulfilled; -function isFulfilled(object) { - return !isPromise(object) || object.inspect().state === "fulfilled"; -} - -Promise.prototype.isFulfilled = function () { - return this.inspect().state === "fulfilled"; -}; - -/** - * @returns whether the given object is a rejected promise. - */ -Q.isRejected = isRejected; -function isRejected(object) { - return isPromise(object) && object.inspect().state === "rejected"; -} - -Promise.prototype.isRejected = function () { - return this.inspect().state === "rejected"; -}; - -//// BEGIN UNHANDLED REJECTION TRACKING - -// This promise library consumes exceptions thrown in handlers so they can be -// handled by a subsequent promise. The exceptions get added to this array when -// they are created, and removed when they are handled. Note that in ES6 or -// shimmed environments, this would naturally be a `Set`. -var unhandledReasons = []; -var unhandledRejections = []; -var trackUnhandledRejections = true; - -function resetUnhandledRejections() { - unhandledReasons.length = 0; - unhandledRejections.length = 0; - - if (!trackUnhandledRejections) { - trackUnhandledRejections = true; - } -} - -function trackRejection(promise, reason) { - if (!trackUnhandledRejections) { - return; - } - - unhandledRejections.push(promise); - if (reason && typeof reason.stack !== "undefined") { - unhandledReasons.push(reason.stack); - } else { - unhandledReasons.push("(no stack) " + reason); - } -} - -function untrackRejection(promise) { - if (!trackUnhandledRejections) { - return; - } - - var at = array_indexOf(unhandledRejections, promise); - if (at !== -1) { - unhandledRejections.splice(at, 1); - unhandledReasons.splice(at, 1); - } -} - -Q.resetUnhandledRejections = resetUnhandledRejections; - -Q.getUnhandledReasons = function () { - // Make a copy so that consumers can't interfere with our internal state. - return unhandledReasons.slice(); -}; - -Q.stopUnhandledRejectionTracking = function () { - resetUnhandledRejections(); - trackUnhandledRejections = false; -}; - -resetUnhandledRejections(); - -//// END UNHANDLED REJECTION TRACKING - -/** - * Constructs a rejected promise. - * @param reason value describing the failure - */ -Q.reject = reject; -function reject(reason) { - var rejection = Promise({ - "when": function (rejected) { - // note that the error has been handled - if (rejected) { - untrackRejection(this); - } - return rejected ? rejected(reason) : this; - } - }, function fallback() { - return this; - }, function inspect() { - return { state: "rejected", reason: reason }; - }); - - // Note that the reason has not been handled. - trackRejection(rejection, reason); - - return rejection; -} - -/** - * Constructs a fulfilled promise for an immediate reference. - * @param value immediate reference - */ -Q.fulfill = fulfill; -function fulfill(value) { - return Promise({ - "when": function () { - return value; - }, - "get": function (name) { - return value[name]; - }, - "set": function (name, rhs) { - value[name] = rhs; - }, - "delete": function (name) { - delete value[name]; - }, - "post": function (name, args) { - // Mark Miller proposes that post with no name should apply a - // promised function. - if (name === null || name === void 0) { - return value.apply(void 0, args); - } else { - return value[name].apply(value, args); - } - }, - "apply": function (thisp, args) { - return value.apply(thisp, args); - }, - "keys": function () { - return object_keys(value); - } - }, void 0, function inspect() { - return { state: "fulfilled", value: value }; - }); -} - -/** - * Converts thenables to Q promises. - * @param promise thenable promise - * @returns a Q promise - */ -function coerce(promise) { - var deferred = defer(); - nextTick(function () { - try { - promise.then(deferred.resolve, deferred.reject, deferred.notify); - } catch (exception) { - deferred.reject(exception); - } - }); - return deferred.promise; -} - -/** - * Annotates an object such that it will never be - * transferred away from this process over any promise - * communication channel. - * @param object - * @returns promise a wrapping of that object that - * additionally responds to the "isDef" message - * without a rejection. - */ -Q.master = master; -function master(object) { - return Promise({ - "isDef": function () {} - }, function fallback(op, args) { - return dispatch(object, op, args); - }, function () { - return Q(object).inspect(); - }); -} - -/** - * Spreads the values of a promised array of arguments into the - * fulfillment callback. - * @param fulfilled callback that receives variadic arguments from the - * promised array - * @param rejected callback that receives the exception if the promise - * is rejected. - * @returns a promise for the return value or thrown exception of - * either callback. - */ -Q.spread = spread; -function spread(value, fulfilled, rejected) { - return Q(value).spread(fulfilled, rejected); -} - -Promise.prototype.spread = function (fulfilled, rejected) { - return this.all().then(function (array) { - return fulfilled.apply(void 0, array); - }, rejected); -}; - -/** - * The async function is a decorator for generator functions, turning - * them into asynchronous generators. Although generators are only part - * of the newest ECMAScript 6 drafts, this code does not cause syntax - * errors in older engines. This code should continue to work and will - * in fact improve over time as the language improves. - * - * ES6 generators are currently part of V8 version 3.19 with the - * --harmony-generators runtime flag enabled. SpiderMonkey has had them - * for longer, but under an older Python-inspired form. This function - * works on both kinds of generators. - * - * Decorates a generator function such that: - * - it may yield promises - * - execution will continue when that promise is fulfilled - * - the value of the yield expression will be the fulfilled value - * - it returns a promise for the return value (when the generator - * stops iterating) - * - the decorated function returns a promise for the return value - * of the generator or the first rejected promise among those - * yielded. - * - if an error is thrown in the generator, it propagates through - * every following yield until it is caught, or until it escapes - * the generator function altogether, and is translated into a - * rejection for the promise returned by the decorated generator. - */ -Q.async = async; -function async(makeGenerator) { - return function () { - // when verb is "send", arg is a value - // when verb is "throw", arg is an exception - function continuer(verb, arg) { - var result; - - // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only - // engine that has a deployed base of browsers that support generators. - // However, SM's generators use the Python-inspired semantics of - // outdated ES6 drafts. We would like to support ES6, but we'd also - // like to make it possible to use generators in deployed browsers, so - // we also support Python-style generators. At some point we can remove - // this block. - - if (typeof StopIteration === "undefined") { - // ES6 Generators - try { - result = generator[verb](arg); - } catch (exception) { - return reject(exception); - } - if (result.done) { - return Q(result.value); - } else { - return when(result.value, callback, errback); - } - } else { - // SpiderMonkey Generators - // FIXME: Remove this case when SM does ES6 generators. - try { - result = generator[verb](arg); - } catch (exception) { - if (isStopIteration(exception)) { - return Q(exception.value); - } else { - return reject(exception); - } - } - return when(result, callback, errback); - } - } - var generator = makeGenerator.apply(this, arguments); - var callback = continuer.bind(continuer, "next"); - var errback = continuer.bind(continuer, "throw"); - return callback(); - }; -} - -/** - * The spawn function is a small wrapper around async that immediately - * calls the generator and also ends the promise chain, so that any - * unhandled errors are thrown instead of forwarded to the error - * handler. This is useful because it's extremely common to run - * generators at the top-level to work with libraries. - */ -Q.spawn = spawn; -function spawn(makeGenerator) { - Q.done(Q.async(makeGenerator)()); -} - -// FIXME: Remove this interface once ES6 generators are in SpiderMonkey. -/** - * Throws a ReturnValue exception to stop an asynchronous generator. - * - * This interface is a stop-gap measure to support generator return - * values in older Firefox/SpiderMonkey. In browsers that support ES6 - * generators like Chromium 29, just use "return" in your generator - * functions. - * - * @param value the return value for the surrounding generator - * @throws ReturnValue exception with the value. - * @example - * // ES6 style - * Q.async(function* () { - * var foo = yield getFooPromise(); - * var bar = yield getBarPromise(); - * return foo + bar; - * }) - * // Older SpiderMonkey style - * Q.async(function () { - * var foo = yield getFooPromise(); - * var bar = yield getBarPromise(); - * Q.return(foo + bar); - * }) - */ -Q["return"] = _return; -function _return(value) { - throw new QReturnValue(value); -} - -/** - * The promised function decorator ensures that any promise arguments - * are settled and passed as values (`this` is also settled and passed - * as a value). It will also ensure that the result of a function is - * always a promise. - * - * @example - * var add = Q.promised(function (a, b) { - * return a + b; - * }); - * add(Q(a), Q(B)); - * - * @param {function} callback The function to decorate - * @returns {function} a function that has been decorated. - */ -Q.promised = promised; -function promised(callback) { - return function () { - return spread([this, all(arguments)], function (self, args) { - return callback.apply(self, args); - }); - }; -} - -/** - * sends a message to a value in a future turn - * @param object* the recipient - * @param op the name of the message operation, e.g., "when", - * @param args further arguments to be forwarded to the operation - * @returns result {Promise} a promise for the result of the operation - */ -Q.dispatch = dispatch; -function dispatch(object, op, args) { - return Q(object).dispatch(op, args); -} - -Promise.prototype.dispatch = function (op, args) { - var self = this; - var deferred = defer(); - nextTick(function () { - self.promiseDispatch(deferred.resolve, op, args); - }); - return deferred.promise; -}; - -/** - * Gets the value of a property in a future turn. - * @param object promise or immediate reference for target object - * @param name name of property to get - * @return promise for the property value - */ -Q.get = function (object, key) { - return Q(object).dispatch("get", [key]); -}; - -Promise.prototype.get = function (key) { - return this.dispatch("get", [key]); -}; - -/** - * Sets the value of a property in a future turn. - * @param object promise or immediate reference for object object - * @param name name of property to set - * @param value new value of property - * @return promise for the return value - */ -Q.set = function (object, key, value) { - return Q(object).dispatch("set", [key, value]); -}; - -Promise.prototype.set = function (key, value) { - return this.dispatch("set", [key, value]); -}; - -/** - * Deletes a property in a future turn. - * @param object promise or immediate reference for target object - * @param name name of property to delete - * @return promise for the return value - */ -Q.del = // XXX legacy -Q["delete"] = function (object, key) { - return Q(object).dispatch("delete", [key]); -}; - -Promise.prototype.del = // XXX legacy -Promise.prototype["delete"] = function (key) { - return this.dispatch("delete", [key]); -}; - -/** - * Invokes a method in a future turn. - * @param object promise or immediate reference for target object - * @param name name of method to invoke - * @param value a value to post, typically an array of - * invocation arguments for promises that - * are ultimately backed with `resolve` values, - * as opposed to those backed with URLs - * wherein the posted value can be any - * JSON serializable object. - * @return promise for the return value - */ -// bound locally because it is used by other methods -Q.mapply = // XXX As proposed by "Redsandro" -Q.post = function (object, name, args) { - return Q(object).dispatch("post", [name, args]); -}; - -Promise.prototype.mapply = // XXX As proposed by "Redsandro" -Promise.prototype.post = function (name, args) { - return this.dispatch("post", [name, args]); -}; - -/** - * Invokes a method in a future turn. - * @param object promise or immediate reference for target object - * @param name name of method to invoke - * @param ...args array of invocation arguments - * @return promise for the return value - */ -Q.send = // XXX Mark Miller's proposed parlance -Q.mcall = // XXX As proposed by "Redsandro" -Q.invoke = function (object, name /*...args*/) { - return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); -}; - -Promise.prototype.send = // XXX Mark Miller's proposed parlance -Promise.prototype.mcall = // XXX As proposed by "Redsandro" -Promise.prototype.invoke = function (name /*...args*/) { - return this.dispatch("post", [name, array_slice(arguments, 1)]); -}; - -/** - * Applies the promised function in a future turn. - * @param object promise or immediate reference for target function - * @param args array of application arguments - */ -Q.fapply = function (object, args) { - return Q(object).dispatch("apply", [void 0, args]); -}; - -Promise.prototype.fapply = function (args) { - return this.dispatch("apply", [void 0, args]); -}; - -/** - * Calls the promised function in a future turn. - * @param object promise or immediate reference for target function - * @param ...args array of application arguments - */ -Q["try"] = -Q.fcall = function (object /* ...args*/) { - return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]); -}; - -Promise.prototype.fcall = function (/*...args*/) { - return this.dispatch("apply", [void 0, array_slice(arguments)]); -}; - -/** - * Binds the promised function, transforming return values into a fulfilled - * promise and thrown errors into a rejected one. - * @param object promise or immediate reference for target function - * @param ...args array of application arguments - */ -Q.fbind = function (object /*...args*/) { - var promise = Q(object); - var args = array_slice(arguments, 1); - return function fbound() { - return promise.dispatch("apply", [ - this, - args.concat(array_slice(arguments)) - ]); - }; -}; -Promise.prototype.fbind = function (/*...args*/) { - var promise = this; - var args = array_slice(arguments); - return function fbound() { - return promise.dispatch("apply", [ - this, - args.concat(array_slice(arguments)) - ]); - }; -}; - -/** - * Requests the names of the owned properties of a promised - * object in a future turn. - * @param object promise or immediate reference for target object - * @return promise for the keys of the eventually settled object - */ -Q.keys = function (object) { - return Q(object).dispatch("keys", []); -}; - -Promise.prototype.keys = function () { - return this.dispatch("keys", []); -}; - -/** - * Turns an array of promises into a promise for an array. If any of - * the promises gets rejected, the whole array is rejected immediately. - * @param {Array*} an array (or promise for an array) of values (or - * promises for values) - * @returns a promise for an array of the corresponding values - */ -// By Mark Miller -// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled -Q.all = all; -function all(promises) { - return when(promises, function (promises) { - var countDown = 0; - var deferred = defer(); - array_reduce(promises, function (undefined, promise, index) { - var snapshot; - if ( - isPromise(promise) && - (snapshot = promise.inspect()).state === "fulfilled" - ) { - promises[index] = snapshot.value; - } else { - ++countDown; - when( - promise, - function (value) { - promises[index] = value; - if (--countDown === 0) { - deferred.resolve(promises); - } - }, - deferred.reject, - function (progress) { - deferred.notify({ index: index, value: progress }); - } - ); - } - }, void 0); - if (countDown === 0) { - deferred.resolve(promises); - } - return deferred.promise; - }); -} - -Promise.prototype.all = function () { - return all(this); -}; - -/** - * Waits for all promises to be settled, either fulfilled or - * rejected. This is distinct from `all` since that would stop - * waiting at the first rejection. The promise returned by - * `allResolved` will never be rejected. - * @param promises a promise for an array (or an array) of promises - * (or values) - * @return a promise for an array of promises - */ -Q.allResolved = deprecate(allResolved, "allResolved", "allSettled"); -function allResolved(promises) { - return when(promises, function (promises) { - promises = array_map(promises, Q); - return when(all(array_map(promises, function (promise) { - return when(promise, noop, noop); - })), function () { - return promises; - }); - }); -} - -Promise.prototype.allResolved = function () { - return allResolved(this); -}; - -/** - * @see Promise#allSettled - */ -Q.allSettled = allSettled; -function allSettled(promises) { - return Q(promises).allSettled(); -} - -/** - * Turns an array of promises into a promise for an array of their states (as - * returned by `inspect`) when they have all settled. - * @param {Array[Any*]} values an array (or promise for an array) of values (or - * promises for values) - * @returns {Array[State]} an array of states for the respective values. - */ -Promise.prototype.allSettled = function () { - return this.then(function (promises) { - return all(array_map(promises, function (promise) { - promise = Q(promise); - function regardless() { - return promise.inspect(); - } - return promise.then(regardless, regardless); - })); - }); -}; - -/** - * Captures the failure of a promise, giving an oportunity to recover - * with a callback. If the given promise is fulfilled, the returned - * promise is fulfilled. - * @param {Any*} promise for something - * @param {Function} callback to fulfill the returned promise if the - * given promise is rejected - * @returns a promise for the return value of the callback - */ -Q.fail = // XXX legacy -Q["catch"] = function (object, rejected) { - return Q(object).then(void 0, rejected); -}; - -Promise.prototype.fail = // XXX legacy -Promise.prototype["catch"] = function (rejected) { - return this.then(void 0, rejected); -}; - -/** - * Attaches a listener that can respond to progress notifications from a - * promise's originating deferred. This listener receives the exact arguments - * passed to ``deferred.notify``. - * @param {Any*} promise for something - * @param {Function} callback to receive any progress notifications - * @returns the given promise, unchanged - */ -Q.progress = progress; -function progress(object, progressed) { - return Q(object).then(void 0, void 0, progressed); -} - -Promise.prototype.progress = function (progressed) { - return this.then(void 0, void 0, progressed); -}; - -/** - * Provides an opportunity to observe the settling of a promise, - * regardless of whether the promise is fulfilled or rejected. Forwards - * the resolution to the returned promise when the callback is done. - * The callback can return a promise to defer completion. - * @param {Any*} promise - * @param {Function} callback to observe the resolution of the given - * promise, takes no arguments. - * @returns a promise for the resolution of the given promise when - * ``fin`` is done. - */ -Q.fin = // XXX legacy -Q["finally"] = function (object, callback) { - return Q(object)["finally"](callback); -}; - -Promise.prototype.fin = // XXX legacy -Promise.prototype["finally"] = function (callback) { - callback = Q(callback); - return this.then(function (value) { - return callback.fcall().then(function () { - return value; - }); - }, function (reason) { - // TODO attempt to recycle the rejection with "this". - return callback.fcall().then(function () { - throw reason; - }); - }); -}; - -/** - * Terminates a chain of promises, forcing rejections to be - * thrown as exceptions. - * @param {Any*} promise at the end of a chain of promises - * @returns nothing - */ -Q.done = function (object, fulfilled, rejected, progress) { - return Q(object).done(fulfilled, rejected, progress); -}; - -Promise.prototype.done = function (fulfilled, rejected, progress) { - var onUnhandledError = function (error) { - // forward to a future turn so that ``when`` - // does not catch it and turn it into a rejection. - nextTick(function () { - makeStackTraceLong(error, promise); - if (Q.onerror) { - Q.onerror(error); - } else { - throw error; - } - }); - }; - - // Avoid unnecessary `nextTick`ing via an unnecessary `when`. - var promise = fulfilled || rejected || progress ? - this.then(fulfilled, rejected, progress) : - this; - - if (typeof process === "object" && process && process.domain) { - onUnhandledError = process.domain.bind(onUnhandledError); - } - - promise.then(void 0, onUnhandledError); -}; - -/** - * Causes a promise to be rejected if it does not get fulfilled before - * some milliseconds time out. - * @param {Any*} promise - * @param {Number} milliseconds timeout - * @param {Any*} custom error message or Error object (optional) - * @returns a promise for the resolution of the given promise if it is - * fulfilled before the timeout, otherwise rejected. - */ -Q.timeout = function (object, ms, error) { - return Q(object).timeout(ms, error); -}; - -Promise.prototype.timeout = function (ms, error) { - var deferred = defer(); - var timeoutId = setTimeout(function () { - if (!error || "string" === typeof error) { - error = new Error(error || "Timed out after " + ms + " ms"); - error.code = "ETIMEDOUT"; - } - deferred.reject(error); - }, ms); - - this.then(function (value) { - clearTimeout(timeoutId); - deferred.resolve(value); - }, function (exception) { - clearTimeout(timeoutId); - deferred.reject(exception); - }, deferred.notify); - - return deferred.promise; -}; - -/** - * Returns a promise for the given value (or promised value), some - * milliseconds after it resolved. Passes rejections immediately. - * @param {Any*} promise - * @param {Number} milliseconds - * @returns a promise for the resolution of the given promise after milliseconds - * time has elapsed since the resolution of the given promise. - * If the given promise rejects, that is passed immediately. - */ -Q.delay = function (object, timeout) { - if (timeout === void 0) { - timeout = object; - object = void 0; - } - return Q(object).delay(timeout); -}; - -Promise.prototype.delay = function (timeout) { - return this.then(function (value) { - var deferred = defer(); - setTimeout(function () { - deferred.resolve(value); - }, timeout); - return deferred.promise; - }); -}; - -/** - * Passes a continuation to a Node function, which is called with the given - * arguments provided as an array, and returns a promise. - * - * Q.nfapply(FS.readFile, [__filename]) - * .then(function (content) { - * }) - * - */ -Q.nfapply = function (callback, args) { - return Q(callback).nfapply(args); -}; - -Promise.prototype.nfapply = function (args) { - var deferred = defer(); - var nodeArgs = array_slice(args); - nodeArgs.push(deferred.makeNodeResolver()); - this.fapply(nodeArgs).fail(deferred.reject); - return deferred.promise; -}; - -/** - * Passes a continuation to a Node function, which is called with the given - * arguments provided individually, and returns a promise. - * @example - * Q.nfcall(FS.readFile, __filename) - * .then(function (content) { - * }) - * - */ -Q.nfcall = function (callback /*...args*/) { - var args = array_slice(arguments, 1); - return Q(callback).nfapply(args); -}; - -Promise.prototype.nfcall = function (/*...args*/) { - var nodeArgs = array_slice(arguments); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - this.fapply(nodeArgs).fail(deferred.reject); - return deferred.promise; -}; - -/** - * Wraps a NodeJS continuation passing function and returns an equivalent - * version that returns a promise. - * @example - * Q.nfbind(FS.readFile, __filename)("utf-8") - * .then(console.log) - * .done() - */ -Q.nfbind = -Q.denodeify = function (callback /*...args*/) { - var baseArgs = array_slice(arguments, 1); - return function () { - var nodeArgs = baseArgs.concat(array_slice(arguments)); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - Q(callback).fapply(nodeArgs).fail(deferred.reject); - return deferred.promise; - }; -}; - -Promise.prototype.nfbind = -Promise.prototype.denodeify = function (/*...args*/) { - var args = array_slice(arguments); - args.unshift(this); - return Q.denodeify.apply(void 0, args); -}; - -Q.nbind = function (callback, thisp /*...args*/) { - var baseArgs = array_slice(arguments, 2); - return function () { - var nodeArgs = baseArgs.concat(array_slice(arguments)); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - function bound() { - return callback.apply(thisp, arguments); - } - Q(bound).fapply(nodeArgs).fail(deferred.reject); - return deferred.promise; - }; -}; - -Promise.prototype.nbind = function (/*thisp, ...args*/) { - var args = array_slice(arguments, 0); - args.unshift(this); - return Q.nbind.apply(void 0, args); -}; - -/** - * Calls a method of a Node-style object that accepts a Node-style - * callback with a given array of arguments, plus a provided callback. - * @param object an object that has the named method - * @param {String} name name of the method of object - * @param {Array} args arguments to pass to the method; the callback - * will be provided by Q and appended to these arguments. - * @returns a promise for the value or error - */ -Q.nmapply = // XXX As proposed by "Redsandro" -Q.npost = function (object, name, args) { - return Q(object).npost(name, args); -}; - -Promise.prototype.nmapply = // XXX As proposed by "Redsandro" -Promise.prototype.npost = function (name, args) { - var nodeArgs = array_slice(args || []); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); - return deferred.promise; -}; - -/** - * Calls a method of a Node-style object that accepts a Node-style - * callback, forwarding the given variadic arguments, plus a provided - * callback argument. - * @param object an object that has the named method - * @param {String} name name of the method of object - * @param ...args arguments to pass to the method; the callback will - * be provided by Q and appended to these arguments. - * @returns a promise for the value or error - */ -Q.nsend = // XXX Based on Mark Miller's proposed "send" -Q.nmcall = // XXX Based on "Redsandro's" proposal -Q.ninvoke = function (object, name /*...args*/) { - var nodeArgs = array_slice(arguments, 2); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); - return deferred.promise; -}; - -Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send" -Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal -Promise.prototype.ninvoke = function (name /*...args*/) { - var nodeArgs = array_slice(arguments, 1); - var deferred = defer(); - nodeArgs.push(deferred.makeNodeResolver()); - this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); - return deferred.promise; -}; - -/** - * If a function would like to support both Node continuation-passing-style and - * promise-returning-style, it can end its internal promise chain with - * `nodeify(nodeback)`, forwarding the optional nodeback argument. If the user - * elects to use a nodeback, the result will be sent there. If they do not - * pass a nodeback, they will receive the result promise. - * @param object a result (or a promise for a result) - * @param {Function} nodeback a Node.js-style callback - * @returns either the promise or nothing - */ -Q.nodeify = nodeify; -function nodeify(object, nodeback) { - return Q(object).nodeify(nodeback); -} - -Promise.prototype.nodeify = function (nodeback) { - if (nodeback) { - this.then(function (value) { - nextTick(function () { - nodeback(null, value); - }); - }, function (error) { - nextTick(function () { - nodeback(error); - }); - }); - } else { - return this; - } -}; - -// All code before this point will be filtered from stack traces. -var qEndingLine = captureLine(); - -return Q; - -}); - diff --git a/cmd/mist/assets/ext/qml_messaging.js b/cmd/mist/assets/ext/qml_messaging.js deleted file mode 100644 index 031c5efd1..000000000 --- a/cmd/mist/assets/ext/qml_messaging.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -function HandleMessage(data) { - var message; - try { message = JSON.parse(data) } catch(e) {}; - - if(message) { - switch(message.type) { - case "coinbase": - return eth.coinBase(); - case "block": - return eth.blockByNumber(0); - } - } -} diff --git a/cmd/mist/assets/ext/qt_messaging_adapter.js b/cmd/mist/assets/ext/qt_messaging_adapter.js deleted file mode 100644 index 04f8e034a..000000000 --- a/cmd/mist/assets/ext/qt_messaging_adapter.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -window._messagingAdapter = function(data) { - navigator.qt.postMessage(data); -}; - -navigator.qt.onmessage = function(ev) { - var data = JSON.parse(ev.data) - - if(data._event !== undefined) { - eth.trigger(data._event, data.data); - } else { - if(data._seed) { - var cb = eth._callbacks[data._seed]; - if(cb) { - cb.call(this, data.data) - - // Remove the "trigger" callback - delete eth._callbacks[ev._seed]; - } - } - } -} diff --git a/cmd/mist/assets/ext/setup.js b/cmd/mist/assets/ext/setup.js deleted file mode 100644 index 8317937b3..000000000 --- a/cmd/mist/assets/ext/setup.js +++ /dev/null @@ -1,8 +0,0 @@ -(function() { - if (typeof(Promise) === "undefined") - window.Promise = Q.Promise; - - var eth = web3.eth; - - web3.setProvider(new web3.providers.QtProvider()); -})() diff --git a/cmd/mist/assets/ext/string.js b/cmd/mist/assets/ext/string.js deleted file mode 100644 index e8dbd14d4..000000000 --- a/cmd/mist/assets/ext/string.js +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -String.prototype.pad = function(l, r) { - if (r === undefined) { - r = l - if (!(this.substr(0, 2) == "0x" || /^\d+$/.test(this))) - l = 0 - } - var ret = this.bin(); - while (ret.length < l) - ret = "\0" + ret - while (ret.length < r) - ret = ret + "\0" - return ret; -} - -String.prototype.unpad = function() { - var i = this.length; - while (i && this[i - 1] == "\0") - --i - return this.substr(0, i) -} - -String.prototype.bin = function() { - if (this.substr(0, 2) == "0x") { - bytes = [] - var i = 2; - - // Check if it's odd - pad with a zero if so. - if (this.length % 2) - bytes.push(parseInt(this.substr(i++, 1), 16)) - - for (; i < this.length - 1; i += 2) - bytes.push(parseInt(this.substr(i, 2), 16)); - - return String.fromCharCode.apply(String, bytes); - } else if (/^\d+$/.test(this)) - return bigInt(this.substr(0)).toHex().bin() - - // Otherwise we'll return the "String" object instead of an actual string - return this.substr(0, this.length) -} - -String.prototype.unbin = function() { - var i, l, o = ''; - for(i = 0, l = this.length; i < l; i++) { - var n = this.charCodeAt(i).toString(16); - o += n.length < 2 ? '0' + n : n; - } - - return "0x" + o; -} - -String.prototype.dec = function() { - return bigInt(this.substr(0)).toString() -} - -String.prototype.hex = function() { - return bigInt(this.substr(0)).toHex() -} diff --git a/cmd/mist/assets/ext/test.html b/cmd/mist/assets/ext/test.html deleted file mode 100644 index 4bac7d36f..000000000 --- a/cmd/mist/assets/ext/test.html +++ /dev/null @@ -1,44 +0,0 @@ -<!doctype> -<html> -<head> -<title>Tests</title> -</head> - -<body> -<button onclick="test();">Test me</button> - -<script type="text/javascript"> -function test() { - var filter = eth.watch({ - latest: -1, - from: "e6716f9544a56c530d868e4bfbacb172315bdead", - altered: ["aabb", {id: "eeff", "at": "aabb"}], - }); - - filter.changed(function(messages) { - console.log("messages", messages) - }) - - filter.getMessages(function(messages) { - console.log("getMessages", messages) - }); - - eth.getEachStorageAt("9ef0f0d81e040012600b0c1abdef7c48f720f88a", function(entries) { - for(var i = 0; i < entries.length; i++) { - console.log(entries[i].key, " : ", entries[i].value) - } - }) - - eth.getBlock("f70097659f329a09642a27f11338d9269de64f1d4485786e36bfc410832148cd", function(block) { - console.log(block) - }) - - eth.mutan("var a = 10", function(code) { - console.log("code", code) - }); -} -</script> - -</body> - -</html> diff --git a/cmd/mist/assets/miner.png b/cmd/mist/assets/miner.png Binary files differnew file mode 100644 index 000000000..58e3f4dfe --- /dev/null +++ b/cmd/mist/assets/miner.png diff --git a/cmd/mist/assets/qml/depricated_browser.qml b/cmd/mist/assets/qml/depricated_browser.qml new file mode 100644 index 000000000..7056dbbf3 --- /dev/null +++ b/cmd/mist/assets/qml/depricated_browser.qml @@ -0,0 +1,486 @@ +import QtQuick 2.1 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import QtQuick.Controls 1.0; +import QtQuick.Controls.Styles 1.0 +import QtQuick.Layouts 1.0; +import QtQuick.Window 2.1; +import Ethereum 1.0 + +Rectangle { + id: window + anchors.fill: parent + color: "#00000000" + + property var title: "DApps" + property var iconSource: "../browser.png" + property var menuItem + property var hideUrl: true + + property alias url: webview.url + property alias windowTitle: webview.title + property alias webView: webview + + property var cleanPath: false + property var open: function(url) { + if(!window.cleanPath) { + var uri = url; + if(!/.*\:\/\/.*/.test(uri)) { + uri = "http://" + uri; + } + + var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ + + if(reg.test(uri)) { + uri.replace(reg, function(match, pre, domain, path) { + uri = pre; + + var lookup = eth.lookupDomain(domain.substring(0, domain.length - 4)); + var ip = []; + for(var i = 0, l = lookup.length; i < l; i++) { + ip.push(lookup.charCodeAt(i)) + } + + if(ip.length != 0) { + uri += lookup; + } else { + uri += domain; + } + + uri += path; + }); + } + + window.cleanPath = true; + + webview.url = uri; + + //uriNav.text = uri.text.replace(/(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.\w{2,3})(.*)/, "$1$2<span style='color:#CCC'>$3</span>"); + uriNav.text = uri; + } else { + // Prevent inf loop. + window.cleanPath = false; + } + } + + Component.onCompleted: { + webview.url = "http://etherian.io" + } + + function messages(messages, id) { + // Bit of a cheat to get proper JSON + var m = JSON.parse(JSON.parse(JSON.stringify(messages))) + webview.postEvent("eth_changed", id, m); + } + + function onShhMessage(message, id) { + webview.postEvent("shh_changed", id, message) + } + + Item { + objectName: "root" + id: root + anchors.fill: parent + state: "inspectorShown" + + RowLayout { + id: navBar + height: 40 + anchors { + left: parent.left + right: parent.right + leftMargin: 7 + } + + Button { + id: back + onClicked: { + webview.goBack() + } + style: ButtonStyle { + background: Image { + source: "../back.png" + width: 30 + height: 30 + } + } + } + + TextField { + anchors { + left: back.right + right: toggleInspector.left + leftMargin: 10 + rightMargin: 10 + } + text: webview.url; + id: uriNav + y: parent.height / 2 - this.height / 2 + + Keys.onReturnPressed: { + webview.url = this.text; + } + } + + Button { + id: toggleInspector + anchors { + right: parent.right + } + iconSource: "../bug.png" + onClicked: { + if(inspector.visible == true){ + inspector.visible = false + }else{ + inspector.visible = true + inspector.url = webview.experimental.remoteInspectorUrl + } + } + } + } + + // Border + Rectangle { + id: divider + anchors { + left: parent.left + right: parent.right + top: navBar.bottom + } + z: -1 + height: 1 + color: "#CCCCCC" + } + + ScrollView { + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + top: divider.bottom + } + WebView { + objectName: "webView" + id: webview + anchors.fill: parent + + function sendMessage(data) { + webview.experimental.postMessage(JSON.stringify(data)) + } + + experimental.preferences.javascriptEnabled: true + experimental.preferences.webAudioEnabled: true + experimental.preferences.pluginsEnabled: true + experimental.preferences.navigatorQtObjectEnabled: true + experimental.preferences.developerExtrasEnabled: true + experimental.preferences.webGLEnabled: true + experimental.preferences.notificationsEnabled: true + experimental.preferences.localStorageEnabled: true + experimental.userAgent:"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Mist/0.1 Safari/537.36" + + experimental.itemSelector: MouseArea { + // To avoid conflicting with ListView.model when inside Initiator context. + property QtObject selectorModel: model + anchors.fill: parent + onClicked: selectorModel.reject() + + Menu { + visible: true + id: itemSelector + + Instantiator { + model: selectorModel.items + delegate: MenuItem { + text: model.text + onTriggered: { + selectorModel.accept(index) + } + } + onObjectAdded: itemSelector.insertItem(index, object) + onObjectRemoved: itemSelector.removeItem(object) + } + } + + Component.onCompleted: { + itemSelector.popup() + } + } + experimental.userScripts: ["../ext/q.js", "../ext/ethereum.js/lib/web3.js", "../ext/ethereum.js/lib/qt.js", "../ext/setup.js"] + experimental.onMessageReceived: { + //console.log("[onMessageReceived]: ", message.data) + var data = JSON.parse(message.data) + + try { + switch(data.call) { + case "eth_compile": + postData(data._id, eth.compile(data.args[0])) + break + + case "eth_coinbase": + postData(data._id, eth.coinBase()) + + case "eth_account": + postData(data._id, eth.key().address); + + case "eth_istening": + postData(data._id, eth.isListening()) + + break + + case "eth_mining": + postData(data._id, eth.isMining()) + + break + + case "eth_peerCount": + postData(data._id, eth.peerCount()) + + break + + case "eth_countAt": + require(1) + postData(data._id, eth.txCountAt(data.args[0])) + + break + + case "eth_codeAt": + require(1) + var code = eth.codeAt(data.args[0]) + postData(data._id, code); + + break + + case "eth_blockByNumber": + require(1) + var block = eth.blockByNumber(data.args[0]) + postData(data._id, block) + break + + case "eth_blockByHash": + require(1) + var block = eth.blockByHash(data.args[0]) + postData(data._id, block) + break + + require(2) + var block = eth.blockByHash(data.args[0]) + postData(data._id, block.transactions[data.args[1]]) + break + + case "eth_transactionByHash": + case "eth_transactionByNumber": + require(2) + + var block; + if (data.call === "transactionByHash") + block = eth.blockByHash(data.args[0]) + else + block = eth.blockByNumber(data.args[0]) + + var tx = block.transactions.get(data.args[1]) + + postData(data._id, tx) + break + + case "eth_uncleByHash": + case "eth_uncleByNumber": + require(2) + + var block; + if (data.call === "uncleByHash") + block = eth.blockByHash(data.args[0]) + else + block = eth.blockByNumber(data.args[0]) + + var uncle = block.uncles.get(data.args[1]) + + postData(data._id, uncle) + + break + + case "transact": + require(5) + + var tx = eth.transact(data.args) + postData(data._id, tx) + + break + + case "eth_stateAt": + require(2); + + var storage = eth.storageAt(data.args[0], data.args[1]); + postData(data._id, storage) + + break + + case "eth_call": + require(1); + var ret = eth.call(data.args) + postData(data._id, ret) + break + + case "eth_balanceAt": + require(1); + + postData(data._id, eth.balanceAt(data.args[0])); + break + + case "eth_watch": + require(2) + eth.watch(data.args[0], data.args[1]) + + case "eth_disconnect": + require(1) + postData(data._id, null) + break; + + case "eth_newFilterString": + require(1) + var id = eth.newFilterString(data.args[0], window) + postData(data._id, id); + break; + + case "eth_newFilter": + require(1) + var id = eth.newFilter(data.args[0], window) + + postData(data._id, id); + break; + + case "eth_filterLogs": + require(1); + + var messages = eth.messages(data.args[0]); + var m = JSON.parse(JSON.parse(JSON.stringify(messages))) + postData(data._id, m); + + break; + + case "eth_deleteFilter": + require(1); + eth.uninstallFilter(data.args[0]) + break; + + + case "shh_newFilter": + require(1); + var id = shh.watch(data.args[0], window); + postData(data._id, id); + break; + + case "shh_newIdentity": + var id = shh.newIdentity() + postData(data._id, id) + + break + + case "shh_post": + require(1); + + var params = data.args[0]; + var fields = ["payload", "to", "from"]; + for(var i = 0; i < fields.length; i++) { + params[fields[i]] = params[fields[i]] || ""; + } + if(typeof params.payload !== "object") { params.payload = [params.payload]; } //params.payload = params.payload.join(""); } + params.topics = params.topics || []; + params.priority = params.priority || 1000; + params.ttl = params.ttl || 100; + + shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl); + + break; + + case "shh_getMessages": + require(1); + + var m = shh.messages(data.args[0]); + var messages = JSON.parse(JSON.parse(JSON.stringify(m))); + postData(data._id, messages); + + break; + + case "ssh_newGroup": + postData(data._id, ""); + break; + } + } catch(e) { + console.log(data.call + ": " + e) + + postData(data._id, null); + } + } + + function post(seed, data) { + postData(data._id, data) + } + function require(args, num) { + if(args.length < num) { + throw("required argument count of "+num+" got "+args.length); + } + } + function postData(seed, data) { + webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) + } + function postEvent(event, id, data) { + webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event})) + } + function onWatchedCb(data, id) { + var messages = JSON.parse(data) + postEvent("watched:"+id, messages) + } + function onNewBlockCb(block) { + postEvent("block:new", block) + } + function onObjectChangeCb(stateObject) { + postEvent("object:"+stateObject.address(), stateObject) + } + function onStorageChangeCb(storageObject) { + var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); + postEvent(ev, [storageObject.address, storageObject.value]) + } + } + } + + Rectangle { + id: sizeGrip + color: "gray" + visible: false + height: 10 + anchors { + left: root.left + right: root.right + } + y: Math.round(root.height * 2 / 3) + + MouseArea { + anchors.fill: parent + drag.target: sizeGrip + drag.minimumY: 0 + drag.maximumY: root.height + drag.axis: Drag.YAxis + } + } + + WebView { + id: inspector + visible: false + anchors { + left: root.left + right: root.right + top: sizeGrip.bottom + bottom: root.bottom + } + } + + states: [ + State { + name: "inspectorShown" + PropertyChanges { + target: inspector + } + } + ] + } +} diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml index cfd227b49..439f7888c 100644 --- a/cmd/mist/assets/qml/main.qml +++ b/cmd/mist/assets/qml/main.qml @@ -12,26 +12,15 @@ import "../ext/http.js" as Http ApplicationWindow { id: root - property alias miningButtonText: miningButton.text property var ethx : Eth.ethx - property var browser width: 1200 height: 820 - minimumHeight: 300 + minimumHeight: 800 + minimumWidth: 600 title: "Mist" - // This signal is used by the filter API. The filter API connects using this signal handler from - // the different QML files and plugins. - signal messages(var messages, int id); - function invokeFilterCallback(data, receiverSeed) { - //var messages = JSON.parse(data) - // Signal handler - messages(data, receiverSeed); - root.browser.view.messages(data, receiverSeed); - } - TextField { id: copyElementHax visible: false @@ -46,20 +35,31 @@ ApplicationWindow { // Takes care of loading all default plugins Component.onCompleted: { var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); - var browser = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true}); - root.browser = browser; + addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true}); addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"}); + addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"}); - addPlugin("./views/jeffcoin/jeffcoin.qml", {noAdd: true, close: false, section: "apps"}) - mainSplit.setView(wallet.view, wallet.menuItem); - // Call the ready handler - gui.done(); + newBrowserTab("http://etherian.io"); + + // Command setup + gui.sendCommand(0) + } + + function activeView(view, menuItem) { + mainSplit.setView(view, menuItem) + if (view.hideUrl) { + urlPane.visible = false; + mainView.anchors.top = rootView.top + } else { + urlPane.visible = true; + mainView.anchors.top = divider.bottom + } } function addViews(view, path, options) { @@ -103,10 +103,17 @@ ApplicationWindow { return views } catch(e) { - ethx.note(e) + console.log(e) } } + function newBrowserTab(url) { + var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true}); + window.view.url = url; + window.menuItem.title = "Mist"; + activeView(window.view, window.menuItem); + } + menuBar: MenuBar { Menu { title: "File" @@ -118,13 +125,6 @@ ApplicationWindow { } } - /* - MenuItem { - text: "Browser" - onTriggered: eth.openBrowser() - } - */ - MenuItem { text: "Add plugin" onTriggered: { @@ -134,6 +134,14 @@ ApplicationWindow { } } + MenuItem { + text: "New tab" + shortcut: "Ctrl+t" + onTriggered: { + newBrowserTab("http://etherian.io"); + } + } + MenuSeparator {} MenuItem { @@ -193,21 +201,6 @@ ApplicationWindow { } MenuSeparator {} - - /* - MenuItem { - id: miningSpeed - text: "Mining: Turbo" - onTriggered: { - gui.toggleTurboMining() - if(text == "Mining: Turbo") { - text = "Mining: Normal"; - } else { - text = "Mining: Turbo"; - } - } - } - */ } Menu { @@ -252,29 +245,18 @@ ApplicationWindow { } statusBar: StatusBar { - height: 32 + //height: 32 id: statusBar - RowLayout { - Button { - id: miningButton - text: "Start Mining" - onClicked: { - gui.toggleMining() - } - } - - RowLayout { - Label { - id: walletValueLabel + Label { + //y: 6 + id: walletValueLabel - font.pixelSize: 10 - styleColor: "#797979" - } - } + font.pixelSize: 10 + styleColor: "#797979" } Label { - y: 6 + //y: 6 objectName: "miningLabel" visible: true font.pixelSize: 10 @@ -283,7 +265,7 @@ ApplicationWindow { } Label { - y: 6 + //y: 6 id: lastBlockLabel objectName: "lastBlockLabel" visible: true @@ -294,17 +276,19 @@ ApplicationWindow { } ProgressBar { + visible: false id: downloadIndicator value: 0 objectName: "downloadIndicator" - y: 3 + y: -4 x: statusBar.width / 2 - this.width / 2 width: 160 } Label { + visible: false objectName: "downloadLabel" - y: 7 + //y: 7 anchors.left: downloadIndicator.right anchors.leftMargin: 5 font.pixelSize: 10 @@ -314,7 +298,7 @@ ApplicationWindow { RowLayout { id: peerGroup - y: 7 + //y: 7 anchors.right: parent.right MouseArea { onDoubleClicked: peerWindow.visible = true @@ -323,14 +307,9 @@ ApplicationWindow { Label { id: peerLabel - font.pixelSize: 8 + font.pixelSize: 10 text: "0 / 0" } - Image { - id: peerImage - width: 10; height: 10 - source: "../network.png" - } } } @@ -352,9 +331,6 @@ ApplicationWindow { views[i].menuItem.setSelection(false) } view.visible = true - - //menu.border.color = "#CCCCCC" - //menu.color = "#FFFFFFFF" menu.setSelection(true) } @@ -460,7 +436,7 @@ ApplicationWindow { MouseArea { anchors.fill: parent onClicked: { - mainSplit.setView(view, menuItem) + activeView(view, menuItem); } } @@ -514,7 +490,15 @@ ApplicationWindow { this.view.destroy() this.destroy() + for (var i = 0; i < mainSplit.views.length; i++) { + var view = mainSplit.views[i]; + if (view.menuItem === this) { + mainSplit.views.splice(i, 1); + break; + } + } gui.removePlugin(this.path) + activeView(mainSplit.views[0].view, mainSplit.views[0].menuItem); } } } @@ -538,7 +522,6 @@ ApplicationWindow { } var comp = menuItemTemplate.createObject(section) - comp.view = view comp.title = view.title @@ -579,7 +562,7 @@ ApplicationWindow { Text { - text: "APPS" + text: "NET" font.bold: true anchors { left: parent.left @@ -622,6 +605,7 @@ ApplicationWindow { * Main view ********************/ Rectangle { + id: rootView anchors.right: parent.right anchors.left: menu.right anchors.bottom: parent.bottom @@ -655,8 +639,7 @@ ApplicationWindow { Keys.onReturnPressed: { if(/^https?/.test(this.text)) { - root.browser.view.open(this.text); - mainSplit.setView(root.browser.view, root.browser.menuItem); + newBrowserTab(this.text); } else { addPlugin(this.text, {close: true, section: "apps"}) } @@ -786,12 +769,9 @@ ApplicationWindow { anchors.fill: parent id: peerTable model: peerModel - TableViewColumn{width: 100; role: "ip" ; title: "IP" } - TableViewColumn{width: 60; role: "port" ; title: "Port" } - TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } - TableViewColumn{width: 100; role: "latency"; title: "Latency" } + TableViewColumn{width: 200; role: "ip" ; title: "IP" } TableViewColumn{width: 260; role: "version" ; title: "Version" } - TableViewColumn{width: 80; role: "caps" ; title: "Capabilities" } + TableViewColumn{width: 180; role: "caps" ; title: "Capabilities" } } } } @@ -802,8 +782,8 @@ ApplicationWindow { title: "About" minimumWidth: 350 maximumWidth: 350 - maximumHeight: 200 - minimumHeight: 200 + maximumHeight: 280 + minimumHeight: 280 Image { id: aboutIcon @@ -813,7 +793,7 @@ ApplicationWindow { smooth: true source: "../facet.png" x: 10 - y: 10 + y: 30 } Text { @@ -822,7 +802,7 @@ ApplicationWindow { anchors.top: parent.top anchors.topMargin: 30 font.pointSize: 12 - text: "<h2>Mist (0.6.5)</h2><h4>Amalthea</h4><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br><h3>Building</h3>Maran Hidskes" + text: "<h2>Mist (0.7.10)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br><h3>UX</h3>Alex van de Sande<br>" } } @@ -881,12 +861,15 @@ ApplicationWindow { model: ListModel { id: pastPeers } Component.onCompleted: { - var ips = eth.pastPeers() - for(var i = 0; i < ips.length; i++) { - pastPeers.append({text: ips.get(i)}) - } - - pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"}) + pastPeers.insert(0, {text: "poc-8.ethdev.com:30303"}) + /* + var ips = eth.pastPeers() + for(var i = 0; i < ips.length; i++) { + pastPeers.append({text: ips.get(i)}) + } + + pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"}) + */ } } diff --git a/cmd/mist/assets/qml/views/browser.qml b/cmd/mist/assets/qml/views/browser.qml new file mode 100644 index 000000000..277a5b7eb --- /dev/null +++ b/cmd/mist/assets/qml/views/browser.qml @@ -0,0 +1,211 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.0; +import QtQuick.Controls.Styles 1.0 +import QtQuick.Layouts 1.0; +import QtWebEngine 1.0 +//import QtWebEngine.experimental 1.0 +import QtQuick.Window 2.0; + +Rectangle { + id: window + anchors.fill: parent + color: "#00000000" + + property var title: "" + property var iconSource: "../browser.png" + property var menuItem + property var hideUrl: true + + property alias url: webview.url + property alias windowTitle: webview.title + property alias webView: webview + + property var cleanPath: false + property var open: function(url) { + if(!window.cleanPath) { + var uri = url; + if(!/.*\:\/\/.*/.test(uri)) { + uri = "http://" + uri; + } + + var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ + + if(reg.test(uri)) { + uri.replace(reg, function(match, pre, domain, path) { + uri = pre; + + var lookup = eth.lookupDomain(domain.substring(0, domain.length - 4)); + var ip = []; + for(var i = 0, l = lookup.length; i < l; i++) { + ip.push(lookup.charCodeAt(i)) + } + + if(ip.length != 0) { + uri += lookup; + } else { + uri += domain; + } + + uri += path; + }); + } + + window.cleanPath = true; + + webview.url = uri; + + //uriNav.text = uri.text.replace(/(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.\w{2,3})(.*)/, "$1$2<span style='color:#CCC'>$3</span>"); + uriNav.text = uri; + } else { + // Prevent inf loop. + window.cleanPath = false; + } + } + + Component.onCompleted: { + } + + Item { + objectName: "root" + id: root + anchors.fill: parent + state: "inspectorShown" + + RowLayout { + id: navBar + height: 40 + anchors { + left: parent.left + right: parent.right + leftMargin: 7 + } + + Button { + id: back + onClicked: { + webview.goBack() + } + style: ButtonStyle { + background: Image { + source: "../../back.png" + width: 30 + height: 30 + } + } + } + + TextField { + anchors { + left: back.right + right: toggleInspector.left + leftMargin: 10 + rightMargin: 10 + } + text: webview.url; + id: uriNav + y: parent.height / 2 - this.height / 2 + + Keys.onReturnPressed: { + webview.url = this.text; + } + } + + Button { + id: toggleInspector + anchors { + right: parent.right + } + iconSource: "../../bug.png" + onClicked: { + // XXX soon + return + if(inspector.visible == true){ + inspector.visible = false + }else{ + inspector.visible = true + inspector.url = webview.experimental.remoteInspectorUrl + } + } + } + } + + // Border + Rectangle { + id: divider + anchors { + left: parent.left + right: parent.right + top: navBar.bottom + } + z: -1 + height: 1 + color: "#CCCCCC" + } + + WebEngineView { + objectName: "webView" + id: webview + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + top: divider.bottom + } + + onLoadingChanged: { + if (loadRequest.status == WebEngineView.LoadSucceededStatus) { + webview.runJavaScript("document.title", function(pageTitle) { + menuItem.title = pageTitle; + }); + webview.runJavaScript(eth.readFile("bignumber.min.js")); + webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js")); + } + } + onJavaScriptConsoleMessage: { + console.log(sourceID + ":" + lineNumber + ":" + JSON.stringify(message)); + } + } + + Rectangle { + id: sizeGrip + color: "gray" + visible: false + height: 10 + anchors { + left: root.left + right: root.right + } + y: Math.round(root.height * 2 / 3) + + MouseArea { + anchors.fill: parent + drag.target: sizeGrip + drag.minimumY: 0 + drag.maximumY: root.height + drag.axis: Drag.YAxis + } + } + + WebEngineView { + id: inspector + visible: false + anchors { + left: root.left + right: root.right + top: sizeGrip.bottom + bottom: root.bottom + } + + } + + states: [ + State { + name: "inspectorShown" + PropertyChanges { + target: inspector + } + } + ] + } +} + diff --git a/cmd/mist/assets/qml/views/chain.qml b/cmd/mist/assets/qml/views/chain.qml index c4ceecfc0..6baf757a5 100644 --- a/cmd/mist/assets/qml/views/chain.qml +++ b/cmd/mist/assets/qml/views/chain.qml @@ -109,9 +109,9 @@ Rectangle { } if(initial){ - blockModel.append({size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) + blockModel.append({raw: block.raw, bloom: block.bloom, size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) } else { - blockModel.insert(0, {size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) + blockModel.insert(0, {bloom: block.bloom, size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) } } @@ -136,6 +136,7 @@ Rectangle { Text { text: '<h3>Block details</h3>'; color: "#F2F2F2"} Text { text: '<b>Block number:</b> ' + number + " (Size: " + size + ")"; color: "#F2F2F2"} Text { text: '<b>Hash:</b> ' + hash; color: "#F2F2F2"} + Text { text: '<b>Bloom:</b> ' + bloom; color: "#F2F2F2"} Text { text: '<b>Coinbase:</b> <' + name + '> ' + coinbase; color: "#F2F2F2"} Text { text: '<b>Block found at:</b> ' + prettyTime; color: "#F2F2F2"} Text { text: '<b>Gas used:</b> ' + gasUsed + " / " + gasLimit; color: "#F2F2F2"} @@ -222,11 +223,17 @@ Rectangle { text: "Contract" anchors.top: contractLabel.bottom anchors.left: parent.left - anchors.bottom: popup.bottom + anchors.right: parent.right wrapMode: Text.Wrap - width: parent.width - 30 height: 80 - anchors.leftMargin: 10 + } + TextArea { + id: dumpData + anchors.top: contractData.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: 300 } } property var transactionModel: ListModel { @@ -248,6 +255,7 @@ Rectangle { } } txView.forceActiveFocus() + dumpData.text = bl.raw; } } } diff --git a/cmd/mist/assets/qml/views/info.qml b/cmd/mist/assets/qml/views/info.qml index 3ff551b05..14ee0bce1 100644 --- a/cmd/mist/assets/qml/views/info.qml +++ b/cmd/mist/assets/qml/views/info.qml @@ -28,7 +28,7 @@ Rectangle { text: "Address" } TextField { - text: eth.key().address + text: eth.coinbase() width: 500 } diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml new file mode 100644 index 000000000..193ce37be --- /dev/null +++ b/cmd/mist/assets/qml/views/miner.qml @@ -0,0 +1,273 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.0; +import QtQuick.Layouts 1.0; +import QtQuick.Dialogs 1.0; +import QtQuick.Window 2.1; +import QtQuick.Controls.Styles 1.1 +import Ethereum 1.0 + +Rectangle { + id: root + property var title: "Miner" + property var iconSource: "../miner.png" + property var menuItem + + color: "#00000000" + + ColumnLayout { + spacing: 10 + anchors.fill: parent + + Rectangle { + id: mainPane + color: "#00000000" + anchors { + top: parent.top + bottom: localTxPane.top + left: parent.left + right: parent.right + } + + Rectangle { + id: menu + height: 25 + anchors { + left: parent.left + } + + RowLayout { + id: tools + anchors { + left: parent.left + right: parent.right + } + + Button { + text: "Start" + onClicked: { + eth.setGasPrice(minGasPrice.text || "10000000000000"); + eth.setExtra(blockExtra.text) + if (eth.toggleMining()) { + this.text = "Stop"; + } else { + this.text = "Start"; + } + } + } + + Rectangle { + id: minGasPriceRect + anchors.top: parent.top + anchors.topMargin: 2 + width: 200 + TextField { + id: minGasPrice + placeholderText: "Min Gas: 10000000000000" + width: 200 + validator: RegExpValidator { regExp: /\d*/ } + } + } + + Rectangle { + width: 300 + anchors { + left: minGasPriceRect.right + leftMargin: 5 + top: parent.top + topMargin: 2 + } + + TextField { + id: blockExtra + placeholderText: "Extra" + width: parent.width + maximumLength: 1024 + } + } + } + } + + Column { + anchors { + left: parent.left + right: parent.right + top: menu.bottom + topMargin: 5 + } + + Text { + text: "<b>Merged mining options</b>" + } + + TableView { + id: mergedMiningTable + height: 300 + anchors { + left: parent.left + right: parent.right + } + Component { + id: checkBoxDelegate + + Item { + id: test + CheckBox { + anchors.fill: parent + checked: styleData.value + + onClicked: { + var model = mergedMiningModel.get(styleData.row) + + if (this.checked) { + model.id = txModel.createLocalTx(model.address, "0", "5000", "0", "") + } else { + txModel.removeWithId(model.id); + model.id = 0; + } + } + } + } + } + TableViewColumn{ role: "checked" ; title: "" ; width: 40 ; delegate: checkBoxDelegate } + TableViewColumn{ role: "name" ; title: "Name" ; width: 480 } + model: ListModel { + objectName: "mergedMiningModel" + id: mergedMiningModel + function addMergedMiningOption(model) { + this.append(model); + } + } + Component.onCompleted: { + /* + // XXX Temp. replace with above eventually + var tmpItems = ["JEVCoin", "Some coin", "Other coin", "Etc coin"]; + var address = "e6716f9544a56c530d868e4bfbacb172315bdead"; + for (var i = 0; i < tmpItems.length; i++) { + mergedMiningModel.append({checked: false, name: tmpItems[i], address: address, id: 0, itemId: i}); + } + */ + } + } + } + } + + Rectangle { + id: localTxPane + color: "#ececec" + border.color: "#cccccc" + border.width: 1 + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: 300 + + ColumnLayout { + spacing: 10 + anchors.fill: parent + RowLayout { + id: newLocalTx + anchors { + left: parent.left + leftMargin: 5 + top: parent.top + topMargin: 5 + bottomMargin: 5 + } + + Text { + text: "Local tx" + } + + Rectangle { + width: 250 + color: "#00000000" + anchors.top: parent.top + anchors.topMargin: 2 + + TextField { + id: to + placeholderText: "To" + width: 250 + validator: RegExpValidator { regExp: /[abcdefABCDEF1234567890]*/ } + } + } + TextField { + property var defaultGas: "5000" + id: gas + placeholderText: "Gas" + text: defaultGas + validator: RegExpValidator { regExp: /\d*/ } + } + TextField { + id: gasPrice + placeholderText: "Price" + validator: RegExpValidator { regExp: /\d*/ } + } + TextField { + id: value + placeholderText: "Amount" + text: "0" + validator: RegExpValidator { regExp: /\d*/ } + } + TextField { + id: data + placeholderText: "Data" + validator: RegExpValidator { regExp: /[abcdefABCDEF1234567890]*/ } + } + Button { + text: "Create" + onClicked: { + if (to.text.length == 40 && gasPrice.text.length != 0 && value.text.length != 0 && gas.text.length != 0) { + txModel.createLocalTx(to.text, gasPrice.text, gas.text, value.text, data.text); + + to.text = ""; gasPrice.text = ""; + gas.text = gas.defaultGas; + value.text = "0" + } + } + } + } + + TableView { + id: txTableView + anchors { + top: newLocalTx.bottom + topMargin: 5 + left: parent.left + right: parent.right + bottom: parent.bottom + } + TableViewColumn{ role: "to" ; title: "To" ; width: 480 } + TableViewColumn{ role: "gas" ; title: "Gas" ; width: 100 } + TableViewColumn{ role: "gasPrice" ; title: "Gas Price" ; width: 100 } + TableViewColumn{ role: "value" ; title: "Amount" ; width: 100 } + TableViewColumn{ role: "data" ; title: "Data" ; width: 100 } + + model: ListModel { + id: txModel + Component.onCompleted: { + } + function removeWithId(id) { + for (var i = 0; i < this.count; i++) { + if (txModel.get(i).id == id) { + this.remove(i); + eth.removeLocalTransaction(id) + break; + } + } + } + + function createLocalTx(to, gasPrice, gas, value, data) { + var id = eth.addLocalTransaction(to, data, gas, gasPrice, value) + txModel.insert(0, {to: to, gas: gas, gasPrice: gasPrice, value: value, data: data, id: id}); + + return id + } + } + } + } + } + } +} diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml index a57e7869a..545098284 100644 --- a/cmd/mist/assets/qml/views/wallet.qml +++ b/cmd/mist/assets/qml/views/wallet.qml @@ -16,7 +16,13 @@ Rectangle { anchors.fill: parent function onReady() { - menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address)) + setBalance() + } + + function setBalance() { + balance.text = "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.coinbase())) + if(menuItem) + menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.coinbase())) } ListModel { @@ -39,7 +45,6 @@ Rectangle { Text { id: balance - text: "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.key().address)) font.pixelSize: 24 anchors { horizontalCenter: parent.horizontalCenter @@ -125,8 +130,7 @@ Rectangle { onClicked: { var value = txValue.text + denomModel.get(valueDenom.currentIndex).zeros; var gasPrice = "10000000000000" - var res = eth.transact({from: eth.key().privateKey, to: txTo.text, value: value, gas: "500", gasPrice: gasPrice}) - console.log(res) + var res = eth.transact({from: eth.coinbase(), to: txTo.text, value: value, gas: "500", gasPrice: gasPrice}) } } } @@ -144,26 +148,31 @@ Rectangle { id: txTableView anchors.fill : parent TableViewColumn{ role: "num" ; title: "#" ; width: 30 } - TableViewColumn{ role: "from" ; title: "From" ; width: 280 } - TableViewColumn{ role: "to" ; title: "To" ; width: 280 } + TableViewColumn{ role: "from" ; title: "From" ; width: 340 } + TableViewColumn{ role: "to" ; title: "To" ; width: 340 } TableViewColumn{ role: "value" ; title: "Amount" ; width: 100 } model: ListModel { id: txModel Component.onCompleted: { - var filter = ethx.watch({latest: -1, from: eth.key().address}); - filter.changed(addTxs) - - addTxs(filter.messages()) } function addTxs(messages) { + /* + setBalance() + for(var i = 0; i < messages.length; i++) { var message = messages.get(i); var to = eth.lookupName(message.to); - var from = eth.lookupName(message.from); + var from; + if(message.from.length == 0) { + from = "- MINED -"; + } else { + from = eth.lookupName(message.from); + } txModel.insert(0, {num: txModel.count, from: from, to: to, value: eth.numberToHuman(message.value)}) } + */ } } } diff --git a/cmd/mist/assets/qml/views/whisper.qml b/cmd/mist/assets/qml/views/whisper.qml new file mode 100644 index 000000000..dc097b806 --- /dev/null +++ b/cmd/mist/assets/qml/views/whisper.qml @@ -0,0 +1,74 @@ + +import QtQuick 2.0 +import QtQuick.Controls 1.0; +import QtQuick.Layouts 1.0; +import QtQuick.Dialogs 1.0; +import QtQuick.Window 2.1; +import QtQuick.Controls.Styles 1.1 +import Ethereum 1.0 + +Rectangle { + id: root + property var title: "Whisper Traffic" + property var menuItem + + objectName: "whisperView" + anchors.fill: parent + + property var identity: "" + Component.onCompleted: { + identity = shh.newIdentity() + + var t = shh.watch({}, root) + } + + function onShhMessage(message, i) { + whisperModel.insert(0, {from: message.from, payload: eth.toAscii(message.payload)}) + } + + RowLayout { + id: input + anchors { + left: parent.left + leftMargin: 20 + top: parent.top + topMargin: 20 + } + + TextField { + id: to + placeholderText: "To" + } + TextField { + id: data + placeholderText: "Data" + } + TextField { + id: topics + placeholderText: "topic1, topic2, topic3, ..." + } + Button { + text: "Send" + onClicked: { + shh.post([eth.toHex(data.text)], "", identity, topics.text.split(","), 500, 50) + } + } + } + + TableView { + id: txTableView + anchors { + top: input.bottom + topMargin: 10 + bottom: parent.bottom + left: parent.left + right: parent.right + } + TableViewColumn{ id: fromRole; role: "from" ; title: "From"; width: 300 } + TableViewColumn{ role: "payload" ; title: "Payload" ; width: parent.width - fromRole.width - 2 } + + model: ListModel { + id: whisperModel + } + } +} diff --git a/cmd/mist/assets/qml/webapp.qml b/cmd/mist/assets/qml/webapp.qml deleted file mode 100644 index bd7399dc9..000000000 --- a/cmd/mist/assets/qml/webapp.qml +++ /dev/null @@ -1,413 +0,0 @@ -import QtQuick 2.0 -import QtWebKit 3.0 -import QtWebKit.experimental 1.0 -import QtQuick.Controls 1.0; -import QtQuick.Controls.Styles 1.0 -import QtQuick.Layouts 1.0; -import QtQuick.Window 2.1; -import Ethereum 1.0 - -Rectangle { - id: window - property var title: "Browser" - property var iconSource: "../browser.png" - property var menuItem - - property alias url: webview.url - property alias webView: webview - - property var cleanPath: false - property var open: function(url) { - if(!window.cleanPath) { - var uri = url; - if(!/.*\:\/\/.*/.test(uri)) { - uri = "http://" + uri; - } - - var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ - - if(reg.test(uri)) { - uri.replace(reg, function(match, pre, domain, path) { - uri = pre; - - var lookup = eth.lookupDomain(domain.substring(0, domain.length - 4)); - var ip = []; - for(var i = 0, l = lookup.length; i < l; i++) { - ip.push(lookup.charCodeAt(i)) - } - - if(ip.length != 0) { - uri += lookup; - } else { - uri += domain; - } - - uri += path; - }); - } - - window.cleanPath = true; - - webview.url = uri; - - //uriNav.text = uri.text.replace(/(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.\w{2,3})(.*)/, "$1$2<span style='color:#CCC'>$3</span>"); - uriNav.text = uri; - } else { - // Prevent inf loop. - window.cleanPath = false; - } - } - - Component.onCompleted: { - webview.url = "http://etherian.io" - } - - signal messages(var messages, int id); - onMessages: { - // Bit of a cheat to get proper JSON - var m = JSON.parse(JSON.parse(JSON.stringify(messages))) - webview.postEvent("messages", [m, id]); - } - - Item { - objectName: "root" - id: root - anchors.fill: parent - state: "inspectorShown" - - RowLayout { - id: navBar - height: 40 - anchors { - left: parent.left - right: parent.right - leftMargin: 7 - } - - Button { - id: back - onClicked: { - webview.goBack() - } - style: ButtonStyle { - background: Image { - source: "../back.png" - width: 30 - height: 30 - } - } - } - - TextField { - anchors { - left: back.right - right: toggleInspector.left - leftMargin: 5 - rightMargin: 5 - } - text: "http://etherian.io" - id: uriNav - y: parent.height / 2 - this.height / 2 - - Keys.onReturnPressed: { - webview.url = this.text; - } - } - - Button { - id: toggleInspector - anchors { - right: parent.right - } - iconSource: "../bug.png" - onClicked: { - if(inspector.visible == true){ - inspector.visible = false - }else{ - inspector.visible = true - inspector.url = webview.experimental.remoteInspectorUrl - } - } - } - } - - - WebView { - objectName: "webView" - id: webview - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - top: navBar.bottom - } - - //property var cleanPath: false - onNavigationRequested: { - window.open(request.url.toString()); - } - - function sendMessage(data) { - webview.experimental.postMessage(JSON.stringify(data)) - } - - - experimental.preferences.javascriptEnabled: true - experimental.preferences.navigatorQtObjectEnabled: true - experimental.preferences.developerExtrasEnabled: true - //experimental.userScripts: ["../ext/qt_messaging_adapter.js", "../ext/q.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"] - experimental.userScripts: ["../ext/q.js", "../ext/eth.js/main.js", "../ext/eth.js/qt.js", "../ext/setup.js"] - experimental.onMessageReceived: { - console.log("[onMessageReceived]: ", message.data) - // TODO move to messaging.js - var data = JSON.parse(message.data) - - try { - switch(data.call) { - case "compile": - postData(data._id, eth.compile(data.args[0])) - break - - case "coinbase": - postData(data._id, eth.coinBase()) - - case "account": - postData(data._id, eth.key().address); - - case "isListening": - postData(data._id, eth.isListening()) - - break - - case "isMining": - postData(data._id, eth.isMining()) - - break - - case "peerCount": - postData(data._id, eth.peerCount()) - - break - - case "countAt": - require(1) - postData(data._id, eth.txCountAt(data.args[0])) - - break - - case "codeAt": - require(1) - var code = eth.codeAt(data.args[0]) - postData(data._id, code); - - break - - case "blockByNumber": - require(1) - var block = eth.blockByNumber(data.args[0]) - postData(data._id, block) - break - - case "blockByHash": - require(1) - var block = eth.blockByHash(data.args[0]) - postData(data._id, block) - break - - require(2) - var block = eth.blockByHash(data.args[0]) - postData(data._id, block.transactions[data.args[1]]) - break - - case "transactionByHash": - case "transactionByNumber": - require(2) - - var block; - if (data.call === "transactionByHash") - block = eth.blockByHash(data.args[0]) - else - block = eth.blockByNumber(data.args[0]) - - var tx = block.transactions.get(data.args[1]) - - postData(data._id, tx) - break - - case "uncleByHash": - case "uncleByNumber": - require(2) - - var block; - if (data.call === "uncleByHash") - block = eth.blockByHash(data.args[0]) - else - block = eth.blockByNumber(data.args[0]) - - var uncle = block.uncles.get(data.args[1]) - - postData(data._id, uncle) - - break - - case "transact": - require(5) - - var tx = eth.transact(data.args) - postData(data._id, tx) - - break - - case "stateAt": - require(2); - - var storage = eth.storageAt(data.args[0], data.args[1]); - postData(data._id, storage) - - break - - case "call": - require(1); - var ret = eth.call(data.args) - postData(data._id, ret) - break - - case "balanceAt": - require(1); - - postData(data._id, eth.balanceAt(data.args[0])); - break - - case "watch": - require(2) - eth.watch(data.args[0], data.args[1]) - - case "disconnect": - require(1) - postData(data._id, null) - break; - - case "messages": - require(1); - - var messages = JSON.parse(eth.getMessages(data.args[0])) - postData(data._id, messages) - break - - case "mutan": - require(1) - - var code = eth.compileMutan(data.args[0]) - postData(data._id, "0x"+code) - break; - - case "newFilterString": - require(1) - var id = eth.newFilterString(data.args[0]) - postData(data._id, id); - break; - - case "newFilter": - require(1) - var id = eth.newFilter(data.args[0]) - - postData(data._id, id); - break; - - case "getMessages": - require(1); - - var messages = eth.messages(data.args[0]); - var m = JSON.parse(JSON.parse(JSON.stringify(messages))) - postData(data._id, m); - - break; - - case "deleteFilter": - require(1); - eth.uninstallFilter(data.args[0]) - break; - } - } catch(e) { - console.log(data.call + ": " + e) - - postData(data._id, null); - } - } - - - function post(seed, data) { - postData(data._id, data) - } - - function require(args, num) { - if(args.length < num) { - throw("required argument count of "+num+" got "+args.length); - } - } - function postData(seed, data) { - webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) - } - function postEvent(event, data) { - webview.experimental.postMessage(JSON.stringify({data: data, _event: event})) - } - - function onWatchedCb(data, id) { - var messages = JSON.parse(data) - postEvent("watched:"+id, messages) - } - - function onNewBlockCb(block) { - postEvent("block:new", block) - } - function onObjectChangeCb(stateObject) { - postEvent("object:"+stateObject.address(), stateObject) - } - function onStorageChangeCb(storageObject) { - var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); - postEvent(ev, [storageObject.address, storageObject.value]) - } - } - - - Rectangle { - id: sizeGrip - color: "gray" - visible: false - height: 10 - anchors { - left: root.left - right: root.right - } - y: Math.round(root.height * 2 / 3) - - MouseArea { - anchors.fill: parent - drag.target: sizeGrip - drag.minimumY: 0 - drag.maximumY: root.height - drag.axis: Drag.YAxis - } - } - - WebView { - id: inspector - visible: false - anchors { - left: root.left - right: root.right - top: sizeGrip.bottom - bottom: root.bottom - } - } - - states: [ - State { - name: "inspectorShown" - PropertyChanges { - target: inspector - } - } - ] - } -} diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go index ebdd8ec73..706c789b1 100644 --- a/cmd/mist/bindings.go +++ b/cmd/mist/bindings.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( @@ -22,11 +25,11 @@ import ( "os" "strconv" - "github.com/ethereum/go-ethereum/chain" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/xeth" + "github.com/ethereum/go-ethereum/state" ) type plugin struct { @@ -46,19 +49,19 @@ func (gui *Gui) LogPrint(level logger.LogLevel, msg string) { } */ } -func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (*xeth.JSReceipt, error) { +func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, error) { var data string if len(recipient) == 0 { code, err := ethutil.Compile(d, false) if err != nil { - return nil, err + return "", err } data = ethutil.Bytes2Hex(code) } else { data = ethutil.Bytes2Hex(utils.FormatTransactionData(d)) } - return gui.pipe.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data) + return gui.xeth.Transact(recipient, value, gas, gasPrice, data) } func (gui *Gui) SetCustomIdentifier(customIdentifier string) { @@ -70,14 +73,10 @@ func (gui *Gui) GetCustomIdentifier() string { return gui.clientIdentity.GetCustomIdentifier() } -func (gui *Gui) ToggleTurboMining() { - gui.miner.ToggleTurbo() -} - // functions that allow Gui to implement interface guilogger.LogSystem func (gui *Gui) SetLogLevel(level logger.LogLevel) { gui.logLevel = level - gui.stdLog.SetLogLevel(level) + gui.eth.Logger().SetLogLevel(level) gui.config.Save("loglevel", level) } @@ -108,9 +107,9 @@ func (self *Gui) DumpState(hash, path string) { var stateDump []byte if len(hash) == 0 { - stateDump = self.eth.BlockManager().CurrentState().Dump() + stateDump = self.eth.ChainManager().State().Dump() } else { - var block *chain.Block + var block *types.Block if hash[0] == '#' { i, _ := strconv.Atoi(hash[1:]) block = self.eth.ChainManager().GetBlockByNumber(uint64(i)) @@ -123,7 +122,7 @@ func (self *Gui) DumpState(hash, path string) { return } - stateDump = block.State().Dump() + stateDump = state.New(block.Root(), self.eth.Db()).Dump() } file, err := os.OpenFile(path[7:], os.O_CREATE|os.O_RDWR, os.ModePerm) @@ -137,20 +136,3 @@ func (self *Gui) DumpState(hash, path string) { file.Write(stateDump) } -func (gui *Gui) ToggleMining() { - var txt string - if gui.eth.Mining { - utils.StopMining(gui.eth) - txt = "Start mining" - - gui.getObjectByName("miningLabel").Set("visible", false) - } else { - utils.StartMining(gui.eth) - gui.miner = utils.GetMiner() - txt = "Stop mining" - - gui.getObjectByName("miningLabel").Set("visible", true) - } - - gui.win.Root().Set("miningButtonText", txt) -} diff --git a/cmd/mist/debugger.go b/cmd/mist/debugger.go index a2aae6f0b..dc6a39560 100644 --- a/cmd/mist/debugger.go +++ b/cmd/mist/debugger.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( @@ -24,12 +27,12 @@ import ( "strings" "unicode" - "github.com/ethereum/go-ethereum/chain" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) type DebuggerWindow struct { @@ -37,10 +40,10 @@ type DebuggerWindow struct { engine *qml.Engine lib *UiLib - vm *vm.DebugVm + vm *vm.Vm Db *Debugger - state *state.State + state *state.StateDB } func NewDebuggerWindow(lib *UiLib) *DebuggerWindow { @@ -54,7 +57,7 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow { win := component.CreateWindow(nil) - w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: &vm.DebugVm{}} + w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: &vm.Vm{}} w.Db = NewDebugger(w) return w @@ -81,7 +84,7 @@ func (self *DebuggerWindow) SetData(data string) { func (self *DebuggerWindow) SetAsm(data []byte) { self.win.Root().Call("clearAsm") - dis := chain.Disassemble(data) + dis := core.Disassemble(data) for _, str := range dis { self.win.Root().Call("setAsm", str) } @@ -141,27 +144,24 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data keyPair = self.lib.eth.KeyManager().KeyPair() ) - statedb := self.lib.eth.BlockManager().TransState() - account := self.lib.eth.BlockManager().TransState().GetAccount(keyPair.Address()) + statedb := self.lib.eth.ChainManager().TransState() + account := self.lib.eth.ChainManager().TransState().GetAccount(keyPair.Address()) contract := statedb.NewStateObject([]byte{0}) + contract.SetCode(script) contract.SetBalance(value) self.SetAsm(script) - block := self.lib.eth.ChainManager().CurrentBlock + block := self.lib.eth.ChainManager().CurrentBlock() - callerClosure := vm.NewClosure(&state.Message{}, account, contract, script, gas, gasPrice) - env := utils.NewEnv(statedb, block, account.Address(), value) - evm := vm.NewDebugVm(env) - evm.Dbg = self.Db + env := utils.NewEnv(self.lib.eth.ChainManager(), statedb, block, account.Address(), value) - self.vm = evm - self.Db.done = false self.Logf("callsize %d", len(script)) go func() { - ret, g, err := callerClosure.Call(evm, data) - tot := new(big.Int).Mul(g, gasPrice) - self.Logf("gas usage %v total price = %v (%v)", g, tot, ethutil.CurrencyToString(tot)) + ret, err := env.Call(account, contract.Address(), data, gas, gasPrice, ethutil.Big0) + //ret, g, err := callerClosure.Call(evm, data) + tot := new(big.Int).Mul(env.Gas, gasPrice) + self.Logf("gas usage %v total price = %v (%v)", env.Gas, tot, ethutil.CurrencyToString(tot)) if err != nil { self.Logln("exited with errors:", err) } else { @@ -267,6 +267,9 @@ type storeVal struct { Key, Value string } +func (self *Debugger) Step(evm vm.VirtualMachine, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, context *vm.Context) { +} + func (self *Debugger) BreakHook(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool { self.main.Logln("break on instr:", pc) @@ -312,9 +315,11 @@ func (d *Debugger) halting(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack d.win.Root().Call("setStack", val.String()) } - stateObject.EachStorage(func(key string, node *ethutil.Value) { - d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())}) - }) + it := stateObject.Trie().Iterator() + for it.Next() { + d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", it.Key), fmt.Sprintf("% x", it.Value)}) + + } stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32)) psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64()) diff --git a/cmd/mist/errors.go b/cmd/mist/errors.go index 2069bf26d..255ed07c1 100644 --- a/cmd/mist/errors.go +++ b/cmd/mist/errors.go @@ -1,27 +1,30 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + This file is part of go-ethereum + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( "fmt" "os" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) func ErrorWindow(err error) { diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go index d004f98c5..20ec52e60 100644 --- a/cmd/mist/ext_app.go +++ b/cmd/mist/ext_app.go @@ -1,32 +1,33 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( - "encoding/json" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/javascript" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/ui/qt" "github.com/ethereum/go-ethereum/xeth" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) type AppContainer interface { @@ -36,20 +37,20 @@ type AppContainer interface { Window() *qml.Window Engine() *qml.Engine - NewBlock(*chain.Block) + NewBlock(*types.Block) NewWatcher(chan bool) Messages(state.Messages, string) Post(string, int) } type ExtApplication struct { - *xeth.JSXEth - eth chain.EthManager + *xeth.XEth + eth core.EthManager events event.Subscription watcherQuitChan chan bool - filters map[string]*chain.Filter + filters map[string]*core.Filter container AppContainer lib *UiLib @@ -57,10 +58,10 @@ type ExtApplication struct { func NewExtApplication(container AppContainer, lib *UiLib) *ExtApplication { return &ExtApplication{ - JSXEth: xeth.NewJSXEth(lib.eth), + XEth: xeth.New(lib.eth), eth: lib.eth, watcherQuitChan: make(chan bool), - filters: make(map[string]*chain.Filter), + filters: make(map[string]*core.Filter), container: container, lib: lib, } @@ -80,7 +81,7 @@ func (app *ExtApplication) run() { // Subscribe to events mux := app.lib.eth.EventMux() - app.events = mux.Subscribe(chain.NewBlockEvent{}, state.Messages(nil)) + app.events = mux.Subscribe(core.NewBlockEvent{}, state.Messages(nil)) // Call the main loop go app.mainLoop() @@ -106,16 +107,18 @@ func (app *ExtApplication) stop() { func (app *ExtApplication) mainLoop() { for ev := range app.events.Chan() { switch ev := ev.(type) { - case chain.NewBlockEvent: + case core.NewBlockEvent: app.container.NewBlock(ev.Block) - case state.Messages: - for id, filter := range app.filters { - msgs := filter.FilterMessages(ev) - if len(msgs) > 0 { - app.container.Messages(msgs, id) + /* TODO remove + case state.Messages: + for id, filter := range app.filters { + msgs := filter.FilterMessages(ev) + if len(msgs) > 0 { + app.container.Messages(msgs, id) + } } - } + */ } } } @@ -125,6 +128,7 @@ func (self *ExtApplication) Watch(filterOptions map[string]interface{}, identifi } func (self *ExtApplication) GetMessages(object map[string]interface{}) string { + /* TODO remove me filter := qt.NewFilterFromMap(object, self.eth) messages := filter.Find() @@ -139,4 +143,6 @@ func (self *ExtApplication) GetMessages(object map[string]interface{}) string { } return string(b) + */ + return "" } diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go index 2ae0a0487..9dc3ae10a 100644 --- a/cmd/mist/flags.go +++ b/cmd/mist/flags.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + This file is part of go-ethereum + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( @@ -36,10 +39,13 @@ var ( Identifier string KeyRing string KeyStore string + PMPGateway string StartRpc bool StartWebSockets bool RpcPort int + WsPort int UseUPnP bool + NatType string OutboundPort string ShowGenesis bool AddPeer string @@ -87,7 +93,7 @@ func defaultAssetPath() string { } func defaultDataDir() string { usr, _ := user.Current() - return path.Join(usr.HomeDir, ".mist") + return path.Join(usr.HomeDir, ".ethereum") } var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini") @@ -104,17 +110,20 @@ func Init() { flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)") flag.StringVar(&OutboundPort, "port", "30303", "listening port") flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support") - flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") + flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") - flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") + flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") + flag.BoolVar(&StartRpc, "rpc", true, "start rpc server") flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") + flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") + flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index 5af1b5c7b..edc799abc 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import "C" @@ -23,48 +26,35 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "math/big" + "os" "path" "runtime" "strconv" - "strings" "time" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/wire" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/ui/qt/qwhisper" "github.com/ethereum/go-ethereum/xeth" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) -/* -func LoadExtension(path string) (uintptr, error) { - lib, err := ffi.NewLibrary(path) - if err != nil { - return 0, err - } - - so, err := lib.Fct("sharedObject", ffi.Pointer, nil) - if err != nil { - return 0, err - } - - ptr := so() - - err = lib.Close() - if err != nil { - return 0, err - } +var guilogger = logger.NewLogger("GUI") - return ptr.Interface().(uintptr), nil -} -*/ +type ServEv byte -var guilogger = logger.NewLogger("GUI") +const ( + setup ServEv = iota + update +) type Gui struct { // The main application window @@ -72,39 +62,49 @@ type Gui struct { // QML Engine engine *qml.Engine component *qml.Common - qmlDone bool // The ethereum interface - eth *eth.Ethereum + eth *eth.Ethereum + serviceEvents chan ServEv // The public Ethereum library - uiLib *UiLib + uiLib *UiLib + whisper *qwhisper.Whisper txDb *ethdb.LDBDatabase logLevel logger.LogLevel open bool - pipe *xeth.JSXEth + xeth *xeth.XEth Session string - clientIdentity *wire.SimpleClientIdentity + clientIdentity *p2p.SimpleClientIdentity config *ethutil.ConfigManager plugins map[string]plugin - miner *miner.Miner - stdLog logger.LogSystem + miner *miner.Miner } // Create GUI, but doesn't start it -func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIdentity *wire.SimpleClientIdentity, session string, logLevel int) *Gui { +func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIdentity *p2p.SimpleClientIdentity, session string, logLevel int) *Gui { db, err := ethdb.NewLDBDatabase("tx_database") if err != nil { panic(err) } - pipe := xeth.NewJSXEth(ethereum) - gui := &Gui{eth: ethereum, txDb: db, pipe: pipe, logLevel: logger.LogLevel(logLevel), Session: session, open: false, clientIdentity: clientIdentity, config: config, plugins: make(map[string]plugin)} + xeth := xeth.New(ethereum) + gui := &Gui{eth: ethereum, + txDb: db, + xeth: xeth, + logLevel: logger.LogLevel(logLevel), + Session: session, + open: false, + clientIdentity: clientIdentity, + config: config, + plugins: make(map[string]plugin), + serviceEvents: make(chan ServEv, 1), + } data, _ := ethutil.ReadAllFile(path.Join(ethutil.Config.ExecPath, "plugins.json")) json.Unmarshal([]byte(data), &gui.plugins) @@ -112,14 +112,17 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIden } func (gui *Gui) Start(assetPath string) { - defer gui.txDb.Close() + guilogger.Infoln("Starting GUI") + + go gui.service() + // Register ethereum functions qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ - Init: func(p *xeth.JSBlock, obj qml.Object) { p.Number = 0; p.Hash = "" }, + Init: func(p *xeth.Block, obj qml.Object) { p.Number = 0; p.Hash = "" }, }, { - Init: func(p *xeth.JSTransaction, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, + Init: func(p *xeth.Transaction, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, }, { Init: func(p *xeth.KeyVal, obj qml.Object) { p.Key = ""; p.Value = "" }, }}) @@ -127,47 +130,25 @@ func (gui *Gui) Start(assetPath string) { gui.engine = qml.NewEngine() context := gui.engine.Context() gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath) + gui.whisper = qwhisper.New(gui.eth.Whisper()) // Expose the eth library and the ui library to QML context.SetVar("gui", gui) context.SetVar("eth", gui.uiLib) + context.SetVar("shh", gui.whisper) - /* - vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib") - fmt.Printf("Fetched vec with addr: %#x\n", vec) - if errr != nil { - fmt.Println(errr) - } else { - context.SetVar("vec", (unsafe.Pointer)(vec)) - } - */ - - // Load the main QML interface - data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) - - var win *qml.Window - var err error - var addlog = false - if len(data) == 0 { - win, err = gui.showKeyImport(context) - } else { - win, err = gui.showWallet(context) - addlog = true - } + win, err := gui.showWallet(context) if err != nil { guilogger.Errorln("asset not found: you can set an alternative asset path on the command line using option 'asset_path'", err) panic(err) } - guilogger.Infoln("Starting GUI") gui.open = true win.Show() // only add the gui guilogger after window is shown otherwise slider wont be shown - if addlog { - logger.AddLogSystem(gui) - } + logger.AddLogSystem(gui) win.Wait() // need to silence gui guilogger after window closed otherwise logsystem hangs (but do not save loglevel) @@ -193,18 +174,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) { return nil, err } - gui.win = gui.createWindow(component) - - gui.update() + gui.createWindow(component) return gui.win, nil } -// The done handler will be called by QML when all views have been loaded -func (gui *Gui) Done() { - gui.qmlDone = true -} - func (gui *Gui) ImportKey(filePath string) { } @@ -218,10 +192,8 @@ func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) { } func (gui *Gui) createWindow(comp qml.Object) *qml.Window { - win := comp.CreateWindow(nil) - - gui.win = win - gui.uiLib.win = win + gui.win = comp.CreateWindow(nil) + gui.uiLib.win = gui.win return gui.win } @@ -245,86 +217,71 @@ func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) { return gui.eth.KeyManager().KeyPair().AsStrings() } -func (gui *Gui) setInitialChainManager() { - sBlk := gui.eth.ChainManager().LastBlockHash +func (gui *Gui) setInitialChain(ancientBlocks bool) { + sBlk := gui.eth.ChainManager().LastBlockHash() blk := gui.eth.ChainManager().GetBlock(sBlk) for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) { - sBlk = blk.PrevHash - addr := gui.address() + sBlk = blk.ParentHash() - // Loop through all transactions to see if we missed any while being offline - for _, tx := range blk.Transactions() { - if bytes.Compare(tx.Sender(), addr) == 0 || bytes.Compare(tx.Recipient, addr) == 0 { - if ok, _ := gui.txDb.Get(tx.Hash()); ok == nil { - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + gui.processBlock(blk, true) + } +} + +func (gui *Gui) loadAddressBook() { + /* + view := gui.getObjectByName("infoView") + nameReg := gui.xeth.World().Config().Get("NameReg") + if nameReg != nil { + it := nameReg.Trie().Iterator() + for it.Next() { + if it.Key[0] != 0 { + view.Call("addAddress", struct{ Name, Address string }{string(it.Key), ethutil.Bytes2Hex(it.Value)}) } } } - - gui.processBlock(blk, true) - } + */ } -type address struct { - Name, Address string -} +func (self *Gui) loadMergedMiningOptions() { + /* + view := self.getObjectByName("mergedMiningModel") -func (gui *Gui) loadAddressBook() { - view := gui.getObjectByName("infoView") - view.Call("clearAddress") + mergeMining := self.xeth.World().Config().Get("MergeMining") + if mergeMining != nil { + i := 0 + it := mergeMining.Trie().Iterator() + for it.Next() { + view.Call("addMergedMiningOption", struct { + Checked bool + Name, Address string + Id, ItemId int + }{false, string(it.Key), ethutil.Bytes2Hex(it.Value), 0, i}) - nameReg := gui.pipe.World().Config().Get("NameReg") - if nameReg != nil { - nameReg.EachStorage(func(name string, value *ethutil.Value) { - if name[0] != 0 { - value.Decode() + i++ - view.Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())}) } - }) - } + } + */ } -func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) { - pipe := xeth.New(gui.eth) - nameReg := pipe.World().Config().Get("NameReg") +func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { addr := gui.address() var inout string - if bytes.Compare(tx.Sender(), addr) == 0 { + if bytes.Compare(tx.From(), addr) == 0 { inout = "send" } else { inout = "recv" } var ( - ptx = xeth.NewJSTx(tx, pipe.World().State()) - send = nameReg.Storage(tx.Sender()) - rec = nameReg.Storage(tx.Recipient) - s, r string + ptx = xeth.NewTx(tx) + send = ethutil.Bytes2Hex(tx.From()) + rec = ethutil.Bytes2Hex(tx.To()) ) - - if tx.CreatesContract() { - rec = nameReg.Storage(tx.CreationAddress(pipe.World().State())) - } - - if send.Len() != 0 { - s = strings.Trim(send.Str(), "\x00") - } else { - s = ethutil.Bytes2Hex(tx.Sender()) - } - if rec.Len() != 0 { - r = strings.Trim(rec.Str(), "\x00") - } else { - if tx.CreatesContract() { - r = ethutil.Bytes2Hex(tx.CreationAddress(pipe.World().State())) - } else { - r = ethutil.Bytes2Hex(tx.Recipient) - } - } - ptx.Sender = s - ptx.Address = r + ptx.Sender = send + ptx.Address = rec if window == "post" { //gui.getObjectByName("transactionView").Call("addTx", ptx, inout) @@ -336,7 +293,7 @@ func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) { func (gui *Gui) readPreviousTransactions() { it := gui.txDb.NewIterator() for it.Next() { - tx := chain.NewTransactionFromBytes(it.Value()) + tx := types.NewTransactionFromBytes(it.Value()) gui.insertTransaction("post", tx) @@ -344,9 +301,9 @@ func (gui *Gui) readPreviousTransactions() { it.Release() } -func (gui *Gui) processBlock(block *chain.Block, initial bool) { - name := strings.Trim(gui.pipe.World().Config().Get("NameReg").Storage(block.Coinbase).Str(), "\x00") - b := xeth.NewJSBlock(block) +func (gui *Gui) processBlock(block *types.Block, initial bool) { + name := ethutil.Bytes2Hex(block.Coinbase()) + b := xeth.NewBlock(block) b.Name = name gui.getObjectByName("chainView").Call("addBlock", b, initial) @@ -372,122 +329,135 @@ func (self *Gui) getObjectByName(objectName string) qml.Object { return self.win.Root().ObjectByName(objectName) } -// Simple go routine function that updates the list of peers in the GUI -func (gui *Gui) update() { - // We have to wait for qml to be done loading all the windows. - for !gui.qmlDone { - time.Sleep(500 * time.Millisecond) +func loadJavascriptAssets(gui *Gui) (jsfiles string) { + for _, fn := range []string{"ext/q.js", "ext/eth.js/main.js", "ext/eth.js/qt.js", "ext/setup.js"} { + f, err := os.Open(gui.uiLib.AssetPath(fn)) + if err != nil { + fmt.Println(err) + continue + } + + content, err := ioutil.ReadAll(f) + if err != nil { + fmt.Println(err) + continue + } + jsfiles += string(content) + } + + return +} + +func (gui *Gui) SendCommand(cmd ServEv) { + gui.serviceEvents <- cmd +} + +func (gui *Gui) service() { + for ev := range gui.serviceEvents { + switch ev { + case setup: + go gui.setup() + case update: + go gui.update() + } + } +} + +func (gui *Gui) setup() { + for gui.win == nil { + time.Sleep(time.Millisecond * 200) + } + + for _, plugin := range gui.plugins { + guilogger.Infoln("Loading plugin ", plugin.Name) + gui.win.Root().Call("addPlugin", plugin.Path, "") } go func() { - go gui.setInitialChainManager() + go gui.setInitialChain(false) gui.loadAddressBook() + gui.loadMergedMiningOptions() gui.setPeerInfo() - gui.readPreviousTransactions() }() - for _, plugin := range gui.plugins { - guilogger.Infoln("Loading plugin ", plugin.Name) + gui.whisper.SetView(gui.getObjectByName("whisperView")) - gui.win.Root().Call("addPlugin", plugin.Path, "") - } + gui.SendCommand(update) +} +// Simple go routine function that updates the list of peers in the GUI +func (gui *Gui) update() { peerUpdateTicker := time.NewTicker(5 * time.Second) generalUpdateTicker := time.NewTicker(500 * time.Millisecond) statsUpdateTicker := time.NewTicker(5 * time.Second) - state := gui.eth.BlockManager().TransState() + state := gui.eth.ChainManager().TransState() - unconfirmedFunds := new(big.Int) gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance()))) lastBlockLabel := gui.getObjectByName("lastBlockLabel") miningLabel := gui.getObjectByName("miningLabel") events := gui.eth.EventMux().Subscribe( - eth.ChainSyncEvent{}, - eth.PeerListEvent{}, - chain.NewBlockEvent{}, - chain.TxPreEvent{}, - chain.TxPostEvent{}, - miner.Event{}, + //eth.PeerListEvent{}, + core.NewBlockEvent{}, + core.TxPreEvent{}, + core.TxPostEvent{}, ) - // nameReg := gui.pipe.World().Config().Get("NameReg") - // mux.Subscribe("object:"+string(nameReg.Address()), objectChan) - - go func() { - defer events.Unsubscribe() - for { - select { - case ev, isopen := <-events.Chan(): - if !isopen { - return - } - switch ev := ev.(type) { - case chain.NewBlockEvent: - gui.processBlock(ev.Block, false) - if bytes.Compare(ev.Block.Coinbase, gui.address()) == 0 { - gui.setWalletValue(gui.eth.BlockManager().CurrentState().GetAccount(gui.address()).Balance(), nil) - } - - case chain.TxPreEvent: - tx := ev.Tx - object := state.GetAccount(gui.address()) - - if bytes.Compare(tx.Sender(), gui.address()) == 0 { - unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) - } else if bytes.Compare(tx.Recipient, gui.address()) == 0 { - unconfirmedFunds.Add(unconfirmedFunds, tx.Value) - } - - gui.setWalletValue(object.Balance(), unconfirmedFunds) - gui.insertTransaction("pre", tx) - - case chain.TxPostEvent: - tx := ev.Tx - object := state.GetAccount(gui.address()) - - if bytes.Compare(tx.Sender(), gui.address()) == 0 { - object.SubAmount(tx.Value) - - //gui.getObjectByName("transactionView").Call("addTx", xeth.NewJSTx(tx), "send") - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } else if bytes.Compare(tx.Recipient, gui.address()) == 0 { - object.AddAmount(tx.Value) - - //gui.getObjectByName("transactionView").Call("addTx", xeth.NewJSTx(tx), "recv") - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } - - gui.setWalletValue(object.Balance(), nil) - state.UpdateStateObject(object) - - // case object: - // gui.loadAddressBook() - - case eth.PeerListEvent: - gui.setPeerInfo() - - case miner.Event: - if ev.Type == miner.Started { - gui.miner = ev.Miner - } else { - gui.miner = nil - } + defer events.Unsubscribe() + for { + select { + case ev, isopen := <-events.Chan(): + if !isopen { + return + } + switch ev := ev.(type) { + case core.NewBlockEvent: + gui.processBlock(ev.Block, false) + if bytes.Compare(ev.Block.Coinbase(), gui.address()) == 0 { + gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil) } - case <-peerUpdateTicker.C: - gui.setPeerInfo() - case <-generalUpdateTicker.C: - statusText := "#" + gui.eth.ChainManager().CurrentBlock.Number.String() - lastBlockLabel.Set("text", statusText) + case core.TxPreEvent: + tx := ev.Tx + + tstate := gui.eth.ChainManager().TransState() + cstate := gui.eth.ChainManager().State() + + taccount := tstate.GetAccount(gui.address()) + caccount := cstate.GetAccount(gui.address()) + unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance()) + + gui.setWalletValue(taccount.Balance(), unconfirmedFunds) + gui.insertTransaction("pre", tx) + + case core.TxPostEvent: + tx := ev.Tx + object := state.GetAccount(gui.address()) + + if bytes.Compare(tx.From(), gui.address()) == 0 { + object.SubAmount(tx.Value()) + + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + } else if bytes.Compare(tx.To(), gui.address()) == 0 { + object.AddAmount(tx.Value()) - if gui.miner != nil { - pow := gui.miner.GetPow() - miningLabel.Set("text", "Mining @ "+strconv.FormatInt(pow.GetHashrate(), 10)+"Khash") + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) } + gui.setWalletValue(object.Balance(), nil) + state.UpdateStateObject(object) + } + + case <-peerUpdateTicker.C: + gui.setPeerInfo() + case <-generalUpdateTicker.C: + statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String() + lastBlockLabel.Set("text", statusText) + miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash") + + /* blockLength := gui.eth.BlockPool().BlocksProcessed chainLength := gui.eth.BlockPool().ChainLength @@ -496,15 +466,14 @@ func (gui *Gui) update() { dlWidget = gui.win.Root().ObjectByName("downloadIndicator") dlLabel = gui.win.Root().ObjectByName("downloadLabel") ) - dlWidget.Set("value", pct) dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength)) + */ - case <-statsUpdateTicker.C: - gui.setStatsPane() - } + case <-statsUpdateTicker.C: + gui.setStatsPane() } - }() + } } func (gui *Gui) setStatsPane() { @@ -512,7 +481,7 @@ func (gui *Gui) setStatsPane() { runtime.ReadMemStats(&memStats) statsPane := gui.getObjectByName("statsPane") - statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.8 (%s) ####### + statsPane.Set("text", fmt.Sprintf(`###### Mist %s (%s) ####### eth %d (p2p = %d) @@ -525,8 +494,8 @@ Heap Alloc: %d CGNext: %x NumGC: %d -`, runtime.Version(), - eth.ProtocolVersion, eth.P2PVersion, +`, Version, runtime.Version(), + eth.ProtocolVersion, 2, runtime.NumCPU, runtime.NumGoroutine(), runtime.NumCgoCall(), memStats.Alloc, memStats.HeapAlloc, memStats.NextGC, memStats.NumGC, @@ -535,11 +504,10 @@ NumGC: %d func (gui *Gui) setPeerInfo() { gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers)) - gui.win.Root().Call("resetPeers") - for _, peer := range gui.pipe.Peers() { - gui.win.Root().Call("addPeer", peer) - } + //for _, peer := range gui.xeth.Peers() { + //gui.win.Root().Call("addPeer", peer) + //} } func (gui *Gui) privateKey() string { @@ -549,3 +517,35 @@ func (gui *Gui) privateKey() string { func (gui *Gui) address() []byte { return gui.eth.KeyManager().Address() } + +/* +func LoadExtension(path string) (uintptr, error) { + lib, err := ffi.NewLibrary(path) + if err != nil { + return 0, err + } + + so, err := lib.Fct("sharedObject", ffi.Pointer, nil) + if err != nil { + return 0, err + } + + ptr := so() + + err = lib.Close() + if err != nil { + return 0, err + } + + return ptr.Interface().(uintptr), nil +} +*/ +/* + vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib") + fmt.Printf("Fetched vec with addr: %#x\n", vec) + if errr != nil { + fmt.Println(errr) + } else { + context.SetVar("vec", (unsafe.Pointer)(vec)) + } +*/ diff --git a/cmd/mist/html_container.go b/cmd/mist/html_container.go index 35e351b02..0909a6abd 100644 --- a/cmd/mist/html_container.go +++ b/cmd/mist/html_container.go @@ -1,24 +1,26 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( - "encoding/json" "errors" "fmt" "io/ioutil" @@ -27,13 +29,12 @@ import ( "path" "path/filepath" - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/javascript" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" "github.com/howeyc/fsnotify" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) type HtmlApplication struct { @@ -138,12 +139,13 @@ func (app *HtmlApplication) Window() *qml.Window { return app.win } -func (app *HtmlApplication) NewBlock(block *chain.Block) { - b := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} +func (app *HtmlApplication) NewBlock(block *types.Block) { + b := &xeth.Block{Number: int(block.NumberU64()), Hash: ethutil.Bytes2Hex(block.Hash())} app.webView.Call("onNewBlockCb", b) } func (self *HtmlApplication) Messages(messages state.Messages, id string) { + /* TODO remove me var msgs []javascript.JSMessage for _, m := range messages { msgs = append(msgs, javascript.NewJSMessage(m)) @@ -152,6 +154,7 @@ func (self *HtmlApplication) Messages(messages state.Messages, id string) { b, _ := json.Marshal(msgs) self.webView.Call("onWatchedCb", string(b), id) + */ } func (app *HtmlApplication) Destroy() { diff --git a/cmd/mist/main.go b/cmd/mist/main.go index 457773c14..a66288a3e 100644 --- a/cmd/mist/main.go +++ b/cmd/mist/main.go @@ -1,81 +1,93 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( + "fmt" "os" "runtime" + "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" - "gopkg.in/qml.v1" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/ui/qt/webengine" + "github.com/obscuren/qml" ) const ( ClientIdentifier = "Mist" - Version = "0.7.3" + Version = "0.8.2" ) var ethereum *eth.Ethereum +var mainlogger = logger.NewLogger("MAIN") func run() error { + webengine.Initialize() + // precedence: code-internal flag default < config file < environment variables < command line Init() // parsing command line + tstart := time.Now() config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH") - utils.InitDataDir(Datadir) - - stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile) - - db := utils.NewDatabase() - err := utils.DBSanityCheck(db) + ethereum, err := eth.New(ð.Config{ + Name: ClientIdentifier, + Version: Version, + KeyStore: KeyStore, + DataDir: Datadir, + LogFile: LogFile, + LogLevel: LogLevel, + Identifier: Identifier, + MaxPeers: MaxPeer, + Port: OutboundPort, + NATType: PMPGateway, + PMPGateway: PMPGateway, + KeyRing: KeyRing, + Dial: true, + }) if err != nil { - ErrorWindow(err) - - os.Exit(1) - } - - keyManager := utils.NewKeyManager(KeyStore, Datadir, db) - - // create, import, export keys - utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) - - clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier) - - ethereum = utils.NewEthereum(db, clientIdentity, keyManager, UseUPnP, OutboundPort, MaxPeer) - - if ShowGenesis { - utils.ShowGenesis(ethereum) + mainlogger.Fatalln(err) } + utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) if StartRpc { utils.StartRpc(ethereum, RpcPort) } - gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel) - gui.stdLog = stdLog + if StartWebSockets { + utils.StartWebSockets(ethereum, WsPort) + } + + gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel) utils.RegisterInterrupt(func(os.Signal) { gui.Stop() }) - utils.StartEthereum(ethereum, UseSeed) + go utils.StartEthereum(ethereum, UseSeed) + + fmt.Println("ETH stack took", time.Since(tstart)) + // gui blocks the main thread gui.Start(AssetPath) @@ -97,16 +109,10 @@ func main() { utils.HandleInterrupt() - if StartWebSockets { - utils.StartWebSockets(ethereum) - } - // we need to run the interrupt callbacks in case gui is closed // this skips if we got here by actual interrupt stopping the GUI if !interrupted { utils.RunInterruptCallbacks(os.Interrupt) } - // this blocks the thread - ethereum.WaitForShutdown() logger.Flush() } diff --git a/cmd/mist/qml_container.go b/cmd/mist/qml_container.go index 60013ec2b..9d76d8fe4 100644 --- a/cmd/mist/qml_container.go +++ b/cmd/mist/qml_container.go @@ -1,19 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main @@ -21,11 +25,11 @@ import ( "fmt" "runtime" - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) type QmlApplication struct { @@ -65,8 +69,8 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) { } // Events -func (app *QmlApplication) NewBlock(block *chain.Block) { - pblock := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} +func (app *QmlApplication) NewBlock(block *types.Block) { + pblock := &xeth.Block{Number: int(block.NumberU64()), Hash: ethutil.Bytes2Hex(block.Hash())} app.win.Call("onNewBlockCb", pblock) } diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go index bb978707d..5e141bdaf 100644 --- a/cmd/mist/ui_lib.go +++ b/cmd/mist/ui_lib.go @@ -1,38 +1,38 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library 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 2.1 of the License, or (at your option) any later version. -// -// This library 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 this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - +/* + This file is part of go-ethereum + + go-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. + + go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @authors + * Jeffrey Wilcke <i@jev.io> + */ package main import ( - "bytes" "fmt" + "io/ioutil" "path" - "strconv" - "strings" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/chain" - "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/event/filter" "github.com/ethereum/go-ethereum/javascript" - "github.com/ethereum/go-ethereum/state" - "github.com/ethereum/go-ethereum/ui/qt" + "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/xeth" - "gopkg.in/qml.v1" + "github.com/obscuren/qml" ) type memAddr struct { @@ -42,7 +42,7 @@ type memAddr struct { // UI Library that has some basic functionality exposed type UiLib struct { - *xeth.JSXEth + *xeth.XEth engine *qml.Engine eth *eth.Ethereum connected bool @@ -55,73 +55,35 @@ type UiLib struct { jsEngine *javascript.JSRE filterCallbacks map[int][]int + filterManager *filter.FilterManager + + miner *miner.Miner } func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib { - return &UiLib{JSXEth: xeth.NewJSXEth(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)} + lib := &UiLib{XEth: xeth.New(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)} + lib.miner = miner.New(eth.KeyManager().Address(), eth) + lib.filterManager = filter.NewFilterManager(eth.EventMux()) + go lib.filterManager.Start() + + return lib } func (self *UiLib) Notef(args []interface{}) { guilogger.Infoln(args...) } -func (self *UiLib) LookupDomain(domain string) string { - world := self.World() - - if len(domain) > 32 { - domain = string(crypto.Sha3([]byte(domain))) - } - data := world.Config().Get("DnsReg").StorageString(domain).Bytes() - - // Left padded = A record, Right padded = CNAME - if len(data) > 0 && data[0] == 0 { - data = bytes.TrimLeft(data, "\x00") - var ipSlice []string - for _, d := range data { - ipSlice = append(ipSlice, strconv.Itoa(int(d))) - } - - return strings.Join(ipSlice, ".") - } else { - data = bytes.TrimRight(data, "\x00") - - return string(data) - } -} - -func (self *UiLib) LookupName(addr string) string { - var ( - nameReg = self.World().Config().Get("NameReg") - lookup = nameReg.Storage(ethutil.Hex2Bytes(addr)) - ) - - if lookup.Len() != 0 { - return strings.Trim(lookup.Str(), "\x00") - } - - return addr -} - -func (self *UiLib) LookupAddress(name string) string { - var ( - nameReg = self.World().Config().Get("NameReg") - lookup = nameReg.Storage(ethutil.RightPadBytes([]byte(name), 32)) - ) - - if lookup.Len() != 0 { - return ethutil.Bytes2Hex(lookup.Bytes()) - } - - return "" -} - func (self *UiLib) PastPeers() *ethutil.List { - return ethutil.NewList(eth.PastPeers()) + return ethutil.NewList([]string{}) + //return ethutil.NewList(eth.PastPeers()) } func (self *UiLib) ImportTx(rlpTx string) { - tx := chain.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx)) - self.eth.TxPool().QueueTransaction(tx) + tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx)) + err := self.eth.TxPool().Add(tx) + if err != nil { + guilogger.Infoln("import tx failed ", err) + } } func (self *UiLib) EvalJavascriptFile(path string) { @@ -181,7 +143,9 @@ func (ui *UiLib) Connect(button qml.Object) { } func (ui *UiLib) ConnectToPeer(addr string) { - ui.eth.ConnectToPeer(addr) + if err := ui.eth.SuggestPeer(addr); err != nil { + guilogger.Infoln(err) + } } func (ui *UiLib) AssetPath(p string) string { @@ -190,18 +154,18 @@ func (ui *UiLib) AssetPath(p string) string { func (self *UiLib) StartDbWithContractAndData(contractHash, data string) { dbWindow := NewDebuggerWindow(self) - object := self.eth.BlockManager().CurrentState().GetStateObject(ethutil.Hex2Bytes(contractHash)) + object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash)) if len(object.Code) > 0 { - dbWindow.SetCode("0x" + ethutil.Bytes2Hex(object.Code)) + dbWindow.SetCode(ethutil.Bytes2Hex(object.Code)) } - dbWindow.SetData("0x" + data) + dbWindow.SetData(data) dbWindow.Show() } func (self *UiLib) StartDbWithCode(code string) { dbWindow := NewDebuggerWindow(self) - dbWindow.SetCode("0x" + code) + dbWindow.SetCode(code) dbWindow.Show() } @@ -211,37 +175,133 @@ func (self *UiLib) StartDebugger() { dbWindow.Show() } -func (self *UiLib) NewFilter(object map[string]interface{}) (id int) { +func (self *UiLib) Transact(params map[string]interface{}) (string, error) { + object := mapToTxParams(params) + + return self.XEth.Transact( + object["to"], + object["value"], + object["gas"], + object["gasPrice"], + object["data"], + ) +} + +func (self *UiLib) Compile(code string) (string, error) { + bcode, err := ethutil.Compile(code, false) + if err != nil { + return err.Error(), err + } + + return ethutil.Bytes2Hex(bcode), err +} + +func (self *UiLib) Call(params map[string]interface{}) (string, error) { + object := mapToTxParams(params) + + return self.XEth.Execute( + object["to"], + object["value"], + object["gas"], + object["gasPrice"], + object["data"], + ) +} + +func (self *UiLib) AddLocalTransaction(to, data, gas, gasPrice, value string) int { + return self.miner.AddLocalTx(&miner.LocalTx{ + To: ethutil.Hex2Bytes(to), + Data: ethutil.Hex2Bytes(data), + Gas: gas, + GasPrice: gasPrice, + Value: value, + }) - 1 +} + +func (self *UiLib) RemoveLocalTransaction(id int) { + self.miner.RemoveLocalTx(id) +} + +func (self *UiLib) SetGasPrice(price string) { + self.miner.MinAcceptedGasPrice = ethutil.Big(price) +} + +func (self *UiLib) SetExtra(extra string) { + self.miner.Extra = extra +} + +func (self *UiLib) ToggleMining() bool { + if !self.miner.Mining() { + self.miner.Start() + + return true + } else { + self.miner.Stop() + + return false + } +} + +func (self *UiLib) ToHex(data string) string { + return "0x" + ethutil.Bytes2Hex([]byte(data)) +} + +func (self *UiLib) ToAscii(data string) string { + start := 0 + if len(data) > 1 && data[0:2] == "0x" { + start = 2 + } + return string(ethutil.Hex2Bytes(data[start:])) +} + +/// Ethereum filter methods +func (self *UiLib) NewFilter(object map[string]interface{}, view *qml.Common) (id int) { + /* TODO remove me filter := qt.NewFilterFromMap(object, self.eth) filter.MessageCallback = func(messages state.Messages) { - self.win.Root().Call("invokeFilterCallback", xeth.ToJSMessages(messages), id) + view.Call("messages", xeth.ToMessages(messages), id) } - id = self.eth.InstallFilter(filter) + id = self.filterManager.InstallFilter(filter) return id + */ + return 0 } -func (self *UiLib) NewFilterString(typ string) (id int) { - filter := chain.NewFilter(self.eth) - filter.BlockCallback = func(block *chain.Block) { - self.win.Root().Call("invokeFilterCallback", "{}", id) +func (self *UiLib) NewFilterString(typ string, view *qml.Common) (id int) { + /* TODO remove me + filter := core.NewFilter(self.eth) + filter.BlockCallback = func(block *types.Block) { + view.Call("messages", "{}", id) } - id = self.eth.InstallFilter(filter) + id = self.filterManager.InstallFilter(filter) return id + */ + return 0 } func (self *UiLib) Messages(id int) *ethutil.List { - filter := self.eth.GetFilter(id) + /* TODO remove me + filter := self.filterManager.GetFilter(id) if filter != nil { - messages := xeth.ToJSMessages(filter.Find()) + messages := xeth.ToMessages(filter.Find()) return messages } + */ return ethutil.EmptyList() } +func (self *UiLib) ReadFile(p string) string { + content, err := ioutil.ReadFile(self.AssetPath(path.Join("ext", p))) + if err != nil { + guilogger.Infoln("error reading file", p, ":", err) + } + return string(content) +} + func (self *UiLib) UninstallFilter(id int) { - self.eth.UninstallFilter(id) + self.filterManager.UninstallFilter(id) } func mapToTxParams(object map[string]interface{}) map[string]string { @@ -294,37 +354,3 @@ func mapToTxParams(object map[string]interface{}) map[string]string { return conv } - -func (self *UiLib) Transact(params map[string]interface{}) (*xeth.JSReceipt, error) { - object := mapToTxParams(params) - - return self.JSXEth.Transact( - object["from"], - object["to"], - object["value"], - object["gas"], - object["gasPrice"], - object["data"], - ) -} - -func (self *UiLib) Compile(code string) (string, error) { - bcode, err := ethutil.Compile(code, false) - if err != nil { - return err.Error(), err - } - - return ethutil.Bytes2Hex(bcode), err -} - -func (self *UiLib) Call(params map[string]interface{}) (string, error) { - object := mapToTxParams(params) - - return self.JSXEth.Execute( - object["to"], - object["value"], - object["gas"], - object["gasPrice"], - object["data"], - ) -} |