diff --git a/README.md b/README.md
index 2d4b128fc9..8cdcfe2a6d 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Status](http://cpt-obvious.ethercasts.com:8010/buildstatusimage?builder=go-ether
Ethereum Go Client © 2014 Jeffrey Wilcke.
-Current state: Proof of Concept 0.6.4.
+Current state: Proof of Concept 0.6.5.
For the development package please see the [eth-go package](https://github.com/ethereum/eth-go).
diff --git a/ethereal/assets/debugger/debugger.qml b/ethereal/assets/debugger/debugger.qml
deleted file mode 100644
index 34fe01253d..0000000000
--- a/ethereal/assets/debugger/debugger.qml
+++ /dev/null
@@ -1,377 +0,0 @@
-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
-
-ApplicationWindow {
- id: win
- visible: false
- title: "IceCREAM"
- minimumWidth: 1280
- minimumHeight: 700
- width: 1290
- height: 750
-
- property alias codeText: codeEditor.text
- property alias dataText: rawDataField.text
-
- onClosing: {
- //compileTimer.stop()
- }
-
- MenuBar {
- Menu {
- title: "Debugger"
- MenuItem {
- text: "Run"
- shortcut: "Ctrl+r"
- onTriggered: debugCurrent()
- }
-
- MenuItem {
- text: "Next"
- shortcut: "Ctrl+n"
- onTriggered: dbg.next()
- }
-
- MenuItem {
- text: "Continue"
- shortcut: "Ctrl+g"
- onTriggered: dbg.continue()
- }
- MenuItem {
- text: "Command"
- shortcut: "Ctrl+l"
- onTriggered: {
- dbgCommand.focus = true
- }
- }
- MenuItem {
- text: "Focus code"
- shortcut: "Ctrl+1"
- onTriggered: {
- codeEditor.focus = true
- }
- }
- MenuItem {
- text: "Focus data"
- shortcut: "Ctrl+2"
- onTriggered: {
- rawDataField.focus = true
- }
- }
-
- /*
- MenuItem {
- text: "Close window"
- shortcut: "Ctrl+w"
- onTriggered: {
- win.close()
- }
- }
- */
- }
- }
-
-
- SplitView {
- anchors.fill: parent
- property var asmModel: ListModel {
- id: asmModel
- }
-
- TableView {
- id: asmTableView
- width: 200
- TableViewColumn{ role: "value" ; title: "" ; width: asmTableView.width - 2 }
- model: asmModel
- }
-
- Rectangle {
- color: "#00000000"
- anchors.left: asmTableView.right
- anchors.right: parent.right
- SplitView {
- orientation: Qt.Vertical
- anchors.fill: parent
-
- Rectangle {
- color: "#00000000"
- height: 330
- anchors.left: parent.left
- anchors.right: parent.right
-
- TextArea {
- id: codeEditor
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: settings.left
- focus: true
-
- /*
- Timer {
- id: compileTimer
- interval: 500 ; running: true ; repeat: true
- onTriggered: {
- dbg.autoComp(codeEditor.text)
- }
- }
- */
- }
-
- Column {
- id: settings
- spacing: 5
- width: 300
- height: parent.height
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: parent.bottom
-
- Label {
- text: "Arbitrary data"
- }
- TextArea {
- id: rawDataField
- anchors.left: parent.left
- anchors.right: parent.right
- height: 150
- }
-
- Label {
- text: "Amount"
- }
- TextField {
- id: txValue
- width: 200
- placeholderText: "Amount"
- validator: RegExpValidator { regExp: /\d*/ }
- }
- Label {
- text: "Amount of gas"
- }
- TextField {
- id: txGas
- width: 200
- validator: RegExpValidator { regExp: /\d*/ }
- text: "10000"
- placeholderText: "Gas"
- }
- Label {
- text: "Gas price"
- }
- TextField {
- id: txGasPrice
- width: 200
- placeholderText: "Gas price"
- text: "1000000000000"
- validator: RegExpValidator { regExp: /\d*/ }
- }
- }
- }
-
- SplitView {
- orientation: Qt.Vertical
- id: inspectorPane
- height: 500
-
- SplitView {
- orientation: Qt.Horizontal
- height: 150
-
- TableView {
- id: stackTableView
- property var stackModel: ListModel {
- id: stackModel
- }
- height: parent.height
- width: 300
- TableViewColumn{ role: "value" ; title: "Temp" ; width: 200 }
- model: stackModel
- }
-
- TableView {
- id: memoryTableView
- property var memModel: ListModel {
- id: memModel
- }
- height: parent.height
- width: parent.width - stackTableView.width
- TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
- TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
- model: memModel
- }
- }
-
- Rectangle {
- height: 100
- width: parent.width
- TableView {
- id: storageTableView
- property var memModel: ListModel {
- id: storageModel
- }
- height: parent.height
- width: parent.width
- TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2}
- TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2}
- model: storageModel
- }
- }
-
- Rectangle {
- height: 200
- width: parent.width
- TableView {
- id: logTableView
- property var logModel: ListModel {
- id: logModel
- }
- height: parent.height
- width: parent.width
- TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width - 2 }
- model: logModel
- }
- }
- }
- }
- }
- }
-
- function exec() {
- dbg.execCommand(dbgCommand.text);
- dbgCommand.text = "";
- }
- statusBar: StatusBar {
- height: 30
-
-
- TextField {
- id: dbgCommand
- y: 1
- x: asmTableView.width
- width: 500
- placeholderText: "Debugger (type 'help')"
- Keys.onReturnPressed: {
- exec()
- }
- }
- }
-
- toolBar: ToolBar {
- height: 30
- RowLayout {
- spacing: 5
-
- Button {
- property var enabled: true
- id: debugStart
- onClicked: {
- debugCurrent()
- }
- text: "Debug"
- }
-
- Button {
- property var enabled: true
- id: debugNextButton
- onClicked: {
- dbg.next()
- }
- text: "Next"
- }
-
- Button {
- id: debugContinueButton
- onClicked: {
- dbg.continue()
- }
- text: "Continue"
- }
- }
-
-
- ComboBox {
- id: snippets
- anchors.right: parent.right
- model: ListModel {
- ListElement { text: "Snippets" ; value: "" }
- ListElement { text: "Call Contract" ; value: "var[2] in;\nvar ret;\n\nin[0] = \"arg1\"\nin[1] = 0xdeadbeef\n\nvar success = call(0x0c542ddea93dae0c2fcb2cf175f03ad80d6be9a0, 0, 7000, in, ret)\n\nreturn ret" }
- }
- onCurrentIndexChanged: {
- if(currentIndex != 0) {
- var code = snippets.model.get(currentIndex).value;
- codeEditor.insert(codeEditor.cursorPosition, code)
- }
- }
- }
-
- }
-
- function debugCurrent() {
- dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text)
- }
-
- function setAsm(asm) {
- asmModel.append({asm: asm})
- }
-
- function clearAsm() {
- asmModel.clear()
- }
-
- function setInstruction(num) {
- asmTableView.selection.clear()
- asmTableView.selection.select(num)
- }
-
- function setMem(mem) {
- memModel.append({num: mem.num, value: mem.value})
- }
- function clearMem(){
- memModel.clear()
- }
-
- function setStack(stack) {
- stackModel.append({value: stack})
- }
- function addDebugMessage(message){
- debuggerLog.append({value: message})
- }
-
- function clearStack() {
- stackModel.clear()
- }
-
- function clearStorage() {
- storageModel.clear()
- }
-
- function setStorage(storage) {
- storageModel.append({key: storage.key, value: storage.value})
- }
-
- function setLog(msg) {
- // Remove first item once we've reached max log items
- if(logModel.count > 250) {
- logModel.remove(0)
- }
-
- if(msg.len != 0) {
- if(logTableView.flickableItem.atYEnd) {
- logModel.append({message: msg})
- logTableView.positionViewAtRow(logTableView.rowCount - 1, ListView.Contain)
- } else {
- logModel.append({message: msg})
- }
- }
- }
-
- function clearLog() {
- logModel.clear()
- }
-}
diff --git a/ethereal/assets/ext/filter.js b/ethereal/assets/ext/filter.js
deleted file mode 100644
index 5c1c03aada..0000000000
--- a/ethereal/assets/ext/filter.js
+++ /dev/null
@@ -1,31 +0,0 @@
-var Filter = function(options) {
- this.callbacks = {};
- this.seed = Math.floor(Math.random() * 1000000);
- this.options = options;
-
- if(options == "chain") {
- eth.registerFilterString(options, this.seed);
- } else if(typeof options === "object") {
- eth.registerFilter(options, this.seed);
- }
-};
-
-Filter.prototype.changed = function(callback) {
- var cbseed = Math.floor(Math.random() * 1000000);
- eth.registerFilterCallback(this.seed, cbseed);
-
- var self = this;
- message.connect(function(messages, seed, callbackSeed) {
- if(seed == self.seed && callbackSeed == cbseed) {
- callback.call(self, messages);
- }
- });
-};
-
-Filter.prototype.uninstall = function() {
- eth.uninstallFilter(this.seed)
-}
-
-Filter.prototype.messages = function() {
- return JSON.parse(eth.messages(this.options))
-}
diff --git a/ethereal/assets/ext/pre.js b/ethereal/assets/ext/pre.js
deleted file mode 100644
index 3e8a534e9b..0000000000
--- a/ethereal/assets/ext/pre.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Helper function for generating pseudo callbacks and sending data to the QML part of the application
-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) {
- // Figure out whether the returned data was an array
- // array means multiple return arguments (multiple params)
- if(data.data instanceof Array) {
- cb.apply(this, data.data)
- } else {
- cb.call(this, data.data)
- }
-
- // Remove the "trigger" callback
- delete eth._callbacks[ev._seed];
- }
- }
- }
-}
diff --git a/ethereal/assets/qml/wallet.qml b/ethereal/assets/qml/wallet.qml
deleted file mode 100644
index 90cc42a1fa..0000000000
--- a/ethereal/assets/qml/wallet.qml
+++ /dev/null
@@ -1,753 +0,0 @@
-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
-
-import "../ext/filter.js" as Eth
-
-ApplicationWindow {
- id: root
-
- property alias miningButtonText: miningButton.text
-
-
- width: 900
- height: 600
- minimumHeight: 300
-
- title: "Ether browser"
-
- // This signal is used by the filter API. The filter API connects using this signal handler from
- // the different QML files and plugins.
- signal message(var callback, int seed, int seedCallback);
- function invokeFilterCallback(data, receiverSeed, callbackSeed) {
- var messages = JSON.parse(data)
- // Signal handler
- message(messages, receiverSeed, callbackSeed);
- }
-
- TextField {
- id: copyElementHax
- visible: false
- }
-
- function copyToClipboard(text) {
- copyElementHax.text = text
- copyElementHax.selectAll()
- copyElementHax.copy()
- }
-
- // Takes care of loading all default plugins
- Component.onCompleted: {
- var walletView = addPlugin("./views/wallet.qml", {noAdd: true, section: "ethereum", active: true})
- var historyView = addPlugin("./views/history.qml", {noAdd: true, section: "legacy"})
- var newTxView = addPlugin("./views/transaction.qml", {noAdd: true, section: "legacy"})
- var chainView = addPlugin("./views/chain.qml", {noAdd: true, section: "legacy"})
- var infoView = addPlugin("./views/info.qml", {noAdd: true, section: "legacy"})
- var pendingTxView = addPlugin("./views/pending_tx.qml", {noAdd: true, section: "legacy"})
- var pendingTxView = addPlugin("./views/javascript.qml", {noAdd: true, section: "legacy"})
-
- // Call the ready handler
- gui.done()
-
- }
-
- function addPlugin(path, options) {
- var component = Qt.createComponent(path);
- if(component.status != Component.Ready) {
- if(component.status == Component.Error) {
- console.debug("Error:"+ component.errorString());
- }
-
- return
- }
-
- var views = mainSplit.addComponent(component, options)
- views.menuItem.path = path
-
- mainSplit.views.push(views);
-
- if(!options.noAdd) {
- gui.addPlugin(path)
- }
-
- return views.view
- }
-
- MenuBar {
- Menu {
- title: "File"
- MenuItem {
- text: "Import App"
- shortcut: "Ctrl+o"
- onTriggered: {
- generalFileDialog.show(true, importApp)
- }
- }
-
- MenuItem {
- text: "Browser"
- onTriggered: eth.openBrowser()
- }
-
- MenuItem {
- text: "Add plugin"
- onTriggered: {
- generalFileDialog.show(true, function(path) {
- addPlugin(path, {canClose: true, section: "apps"})
- })
- }
- }
-
- MenuSeparator {}
-
- MenuItem {
- text: "Import key"
- shortcut: "Ctrl+i"
- onTriggered: {
- generalFileDialog.show(true, function(path) {
- gui.importKey(path)
- })
- }
- }
-
- MenuItem {
- text: "Export keys"
- shortcut: "Ctrl+e"
- onTriggered: {
- generalFileDialog.show(false, function(path) {
- })
- }
- }
- }
-
- Menu {
- title: "Developer"
- MenuItem {
- text: "Debugger"
- shortcut: "Ctrl+d"
- onTriggered: eth.startDebugger()
- }
-
- MenuItem {
- text: "Import Tx"
- onTriggered: {
- txImportDialog.visible = true
- }
- }
-
- MenuItem {
- text: "Run JS file"
- onTriggered: {
- generalFileDialog.show(true, function(path) {
- eth.evalJavascriptFile(path)
- })
- }
- }
-
- MenuItem {
- text: "Dump state"
- onTriggered: {
- generalFileDialog.show(false, function(path) {
- // Empty hash for latest
- gui.dumpState("", path)
- })
- }
- }
-
- MenuSeparator {}
-
- MenuItem {
- id: miningSpeed
- text: "Mining: Turbo"
- onTriggered: {
- gui.toggleTurboMining()
- if(text == "Mining: Turbo") {
- text = "Mining: Normal";
- } else {
- text = "Mining: Turbo";
- }
- }
- }
- }
-
- Menu {
- title: "Network"
- MenuItem {
- text: "Add Peer"
- shortcut: "Ctrl+p"
- onTriggered: {
- addPeerWin.visible = true
- }
- }
- MenuItem {
- text: "Show Peers"
- shortcut: "Ctrl+e"
- onTriggered: {
- peerWindow.visible = true
- }
- }
- }
-
- Menu {
- title: "Help"
- MenuItem {
- text: "About"
- onTriggered: {
- aboutWin.visible = true
- }
- }
- }
-
- }
-
- statusBar: StatusBar {
- height: 32
- RowLayout {
- Button {
- id: miningButton
- text: "Start Mining"
- onClicked: {
- gui.toggleMining()
- }
- }
-
- Button {
- id: importAppButton
- text: "Browser"
- onClicked: {
- eth.openBrowser()
- }
- }
-
- RowLayout {
- Label {
- id: walletValueLabel
-
- font.pixelSize: 10
- styleColor: "#797979"
- }
- }
- }
-
- Label {
- y: 6
- objectName: "miningLabel"
- visible: true
- font.pixelSize: 10
- anchors.right: lastBlockLabel.left
- anchors.rightMargin: 5
- }
-
- Label {
- y: 6
- id: lastBlockLabel
- objectName: "lastBlockLabel"
- visible: true
- text: ""
- font.pixelSize: 10
- anchors.right: peerGroup.left
- anchors.rightMargin: 5
- }
-
- ProgressBar {
- id: syncProgressIndicator
- visible: false
- objectName: "syncProgressIndicator"
- y: 3
- width: 140
- indeterminate: true
- anchors.right: peerGroup.left
- anchors.rightMargin: 5
- }
-
- RowLayout {
- id: peerGroup
- y: 7
- anchors.right: parent.right
- MouseArea {
- onDoubleClicked: peerWindow.visible = true
- anchors.fill: parent
- }
-
- Label {
- id: peerLabel
- font.pixelSize: 8
- text: "0 / 0"
- }
- Image {
- id: peerImage
- width: 10; height: 10
- source: "../network.png"
- }
- }
- }
-
-
- property var blockModel: ListModel {
- id: blockModel
- }
-
- SplitView {
- property var views: [];
-
- id: mainSplit
- anchors.fill: parent
- resizing: false
-
- function setView(view, menu) {
- for(var i = 0; i < views.length; i++) {
- views[i].view.visible = false
-
- views[i].menuItem.border.color = "#00000000"
- views[i].menuItem.color = "#00000000"
- }
- view.visible = true
-
- menu.border.color = "#CCCCCC"
- menu.color = "#FFFFFFFF"
- }
-
- function addComponent(component, options) {
- var view = mainView.createView(component, options)
- view.visible = false
- view.anchors.fill = mainView
-
- if( !view.hasOwnProperty("iconSource") ) {
- console.log("Could not load plugin. Property 'iconSourc' not found on view.");
- return;
- }
-
- var menuItem = menu.createMenuItem(view.iconSource, view, options);
- if( view.hasOwnProperty("menuItem") ) {
- view.menuItem = menuItem;
- }
-
- if( view.hasOwnProperty("onReady") ) {
- view.onReady.call(view)
- }
-
- if( options.active ) {
- setView(view, menuItem)
- }
-
-
- return {view: view, menuItem: menuItem}
- }
-
- /*********************
- * Main menu.
- ********************/
- Rectangle {
- id: menu
- Layout.minimumWidth: 180
- Layout.maximumWidth: 180
- anchors.top: parent.top
- color: "#ececec"
-
- Component {
- id: menuItemTemplate
- Rectangle {
- id: menuItem
- property var view;
- property var path;
-
- property alias title: label.text
- property alias icon: icon.source
- property alias secondaryTitle: secondary.text
-
- width: 180
- height: 28
- border.color: "#00000000"
- border.width: 1
- radius: 5
- color: "#00000000"
-
- anchors {
- left: parent.left
- leftMargin: 4
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: {
- mainSplit.setView(view, menuItem)
- }
- }
-
- Image {
- id: icon
- height: 20
- width: 20
- anchors {
- left: parent.left
- verticalCenter: parent.verticalCenter
- leftMargin: 3
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- menuItem.closeApp()
- }
- }
- }
-
- Text {
- id: label
- anchors {
- left: icon.right
- verticalCenter: parent.verticalCenter
- leftMargin: 3
- }
-
- color: "#0D0A01"
- font.pixelSize: 12
- }
-
- Text {
- id: secondary
- anchors {
- right: parent.right
- rightMargin: 8
- verticalCenter: parent.verticalCenter
- }
- color: "#AEADBE"
- font.pixelSize: 12
- }
-
-
- function closeApp() {
- if(this.view.hasOwnProperty("onDestroy")) {
- this.view.onDestroy.call(this.view)
- }
-
- this.view.destroy()
- this.destroy()
- gui.removePlugin(this.path)
- }
- }
- }
-
- function createMenuItem(icon, view, options) {
- if(options === undefined) {
- options = {};
- }
-
- var section;
- switch(options.section) {
- case "ethereum":
- section = menuDefault;
- break;
- case "legacy":
- section = menuLegacy;
- break;
- default:
- section = menuApps;
- break;
- }
-
- var comp = menuItemTemplate.createObject(section)
-
- comp.view = view
- comp.title = view.title
- comp.icon = view.iconSource
- /*
- if(view.secondary !== undefined) {
- comp.secondary = view.secondary
- }
- */
-
- return comp
-
- /*
- if(options.canClose) {
- //comp.closeButton.visible = options.canClose
- }
- */
- }
-
- ColumnLayout {
- id: menuColumn
- y: 10
- width: parent.width
- anchors.left: parent.left
- anchors.right: parent.right
- spacing: 3
-
- Text {
- text: "ETHEREUM"
- font.bold: true
- anchors {
- left: parent.left
- leftMargin: 5
- }
- color: "#888888"
- }
-
- ColumnLayout {
- id: menuDefault
- spacing: 3
- anchors {
- left: parent.left
- right: parent.right
- }
- }
-
-
- Text {
- text: "APPS"
- font.bold: true
- anchors {
- left: parent.left
- leftMargin: 5
- }
- color: "#888888"
- }
-
- ColumnLayout {
- id: menuApps
- spacing: 3
- anchors {
- left: parent.left
- right: parent.right
- }
- }
-
- Text {
- text: "DEBUG"
- font.bold: true
- anchors {
- left: parent.left
- leftMargin: 5
- }
- color: "#888888"
- }
-
- ColumnLayout {
- id: menuLegacy
- spacing: 3
- anchors {
- left: parent.left
- right: parent.right
- }
- }
- }
- }
-
- /*********************
- * Main view
- ********************/
- Rectangle {
- id: mainView
- color: "#00000000"
-
- anchors.right: parent.right
- anchors.left: menu.right
- anchors.bottom: parent.bottom
- anchors.top: parent.top
-
- function createView(component) {
- var view = component.createObject(mainView)
-
- return view;
- }
- }
-
-
- }
-
-
- /******************
- * Dialogs
- *****************/
- FileDialog {
- id: generalFileDialog
- property var callback;
- onAccepted: {
- var path = this.fileUrl.toString();
- callback.call(this, path);
- }
-
- function show(selectExisting, callback) {
- generalFileDialog.callback = callback;
- generalFileDialog.selectExisting = selectExisting;
-
- this.open();
- }
- }
-
-
- /******************
- * Wallet functions
- *****************/
- function importApp(path) {
- var ext = path.split('.').pop()
- if(ext == "html" || ext == "htm") {
- eth.openHtml(path)
- }else if(ext == "qml"){
- addPlugin(path, {canClose: true, section: "apps"})
- }
- }
-
-
- function setWalletValue(value) {
- walletValueLabel.text = value
- }
-
- function loadPlugin(name) {
- console.log("Loading plugin" + name)
- var view = mainView.addPlugin(name)
- }
-
- function setPeers(text) {
- peerLabel.text = text
- }
-
- function addPeer(peer) {
- // We could just append the whole peer object but it cries if you try to alter them
- peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version})
- }
-
- function resetPeers(){
- peerModel.clear()
- }
-
- function timeAgo(unixTs){
- var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000
- return (lapsed + " seconds ago")
- }
-
- function convertToPretty(unixTs){
- var a = new Date(unixTs*1000);
- var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
- var year = a.getFullYear();
- var month = months[a.getMonth()];
- var date = a.getDate();
- var hour = a.getHours();
- var min = a.getMinutes();
- var sec = a.getSeconds();
- var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ;
- return time;
- }
-
- /**********************
- * Windows
- *********************/
- Window {
- id: peerWindow
- //flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
- height: 200
- width: 700
- Rectangle {
- anchors.fill: parent
- property var peerModel: ListModel {
- id: peerModel
- }
- TableView {
- 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: 260; role: "version" ; title: "Version" }
- }
- }
- }
-
- Window {
- id: aboutWin
- visible: false
- title: "About"
- minimumWidth: 350
- maximumWidth: 350
- maximumHeight: 200
- minimumHeight: 200
-
- Image {
- id: aboutIcon
- height: 150
- width: 150
- fillMode: Image.PreserveAspectFit
- smooth: true
- source: "../facet.png"
- x: 10
- y: 10
- }
-
- Text {
- anchors.left: aboutIcon.right
- anchors.leftMargin: 10
- font.pointSize: 12
- text: "
Ethereal - Aitne
Development
Jeffrey Wilcke
Maran Hidskes
Viktor Trón
"
- }
- }
-
- Window {
- id: txImportDialog
- minimumWidth: 270
- maximumWidth: 270
- maximumHeight: 50
- minimumHeight: 50
- TextField {
- id: txImportField
- width: 170
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 10
- onAccepted: {
- }
- }
- Button {
- anchors.left: txImportField.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: 5
- text: "Import"
- onClicked: {
- eth.importTx(txImportField.text)
- txImportField.visible = false
- }
- }
- Component.onCompleted: {
- addrField.focus = true
- }
- }
-
- Window {
- id: addPeerWin
- visible: false
- minimumWidth: 230
- maximumWidth: 230
- maximumHeight: 50
- minimumHeight: 50
-
- TextField {
- id: addrField
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 10
- placeholderText: "address:port"
- onAccepted: {
- eth.connectToPeer(addrField.text)
- addPeerWin.visible = false
- }
- }
- Button {
- anchors.left: addrField.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: 5
- text: "Add"
- onClicked: {
- eth.connectToPeer(addrField.text)
- addPeerWin.visible = false
- }
- }
- Component.onCompleted: {
- addrField.focus = true
- }
- }
- }
diff --git a/ethereal/assets/qml/webapp.qml b/ethereal/assets/qml/webapp.qml
deleted file mode 100644
index ca68600367..0000000000
--- a/ethereal/assets/qml/webapp.qml
+++ /dev/null
@@ -1,347 +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
-
-ApplicationWindow {
- id: window
- title: "Ethereum"
- width: 1000
- height: 800
- minimumHeight: 300
-
- property alias url: webview.url
- property alias webView: webview
-
- 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
- }
- 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
- }
- onTitleChanged: { window.title = title }
-
- property var cleanPath: false
- onNavigationRequested: {
- if(!this.cleanPath) {
- var uri = request.url.toString();
- 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 = ui.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;
- });
- }
-
- this.cleanPath = true;
-
- webview.url = uri;
- } else {
- // Prevent inf loop.
- this.cleanPath = false;
- }
- }
-
-
- experimental.preferences.javascriptEnabled: true
- experimental.preferences.navigatorQtObjectEnabled: true
- experimental.preferences.developerExtrasEnabled: true
- experimental.userScripts: ["../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/ethereum.js"]
- experimental.onMessageReceived: {
- console.log("[onMessageReceived]: ", message.data)
- // TODO move to messaging.js
- var data = JSON.parse(message.data)
-
- try {
- switch(data.call) {
- case "getCoinBase":
- postData(data._seed, eth.coinBase())
-
- break
-
- case "getIsListening":
- postData(data._seed, eth.isListening())
-
- break
-
- case "getIsMining":
- postData(data._seed, eth.isMining())
-
- break
-
- case "getPeerCount":
- postData(data._seed, eth.peerCount())
-
- break
-
- case "getTxCountAt":
- require(1)
- postData(data._seed, eth.txCountAt(data.args[0]))
-
- break
-
- case "getBlockByNumber":
- var block = eth.blockByNumber(data.args[0])
- postData(data._seed, block)
-
- break
-
- case "getBlockByHash":
- var block = eth.blockByHash(data.args[0])
- postData(data._seed, block)
-
- break
-
- case "transact":
- require(5)
-
- var tx = eth.transact(data.args[0], data.args[1], data.args[2],data.args[3],data.args[4],data.args[5])
- postData(data._seed, tx)
-
- break
-
- case "getStorage":
- require(2);
-
- var stateObject = eth.stateObject(data.args[0])
- var storage = stateObject.storageAt(data.args[1])
- postData(data._seed, storage)
-
- break
-
- case "getEachStorage":
- require(1);
- var storage = JSON.parse(eth.eachStorage(data.args[0]))
- postData(data._seed, storage)
-
- break
-
- case "getTransactionsFor":
- require(1);
- var txs = eth.transactionsFor(data.args[0], true)
- postData(data._seed, txs)
-
- break
-
- case "getBalance":
- require(1);
-
- postData(data._seed, eth.stateObject(data.args[0]).value());
-
- break
-
- case "getKey":
- var key = eth.key().privateKey;
-
- postData(data._seed, key)
- break
-
- /*
- case "watch":
- require(1)
- eth.watch(data.args[0], data.args[1]);
-
- break
- */
- case "watch":
- require(2)
- eth.watch(data.args[0], data.args[1])
-
- case "disconnect":
- require(1)
- postData(data._seed, null)
-
- break;
-
- case "getSecretToAddress":
- require(1)
- postData(data._seed, eth.secretToAddress(data.args[0]))
-
- break;
-
- case "messages":
- require(1);
-
- var messages = JSON.parse(eth.getMessages(data.args[0]))
- postData(data._seed, messages)
-
- break
-
- case "mutan":
- require(1)
-
- var code = eth.compileMutan(data.args[0])
- postData(data._seed, "0x"+code)
-
- break;
- }
- } catch(e) {
- console.log(data.call + ": " + e)
-
- postData(data._seed, null);
- }
- }
-
- function post(seed, data) {
- console.log("data", data)
- postData(data._seed, 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, _seed: 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/ethereum/flags.go b/ethereum/flags.go
index 5ed208411b..c488e63143 100644
--- a/ethereum/flags.go
+++ b/ethereum/flags.go
@@ -74,6 +74,7 @@ func Init() {
flag.IntVar(&LogLevel, "loglevel", int(ethlog.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
+ flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]")
flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
diff --git a/ethereum/main.go b/ethereum/main.go
index b7c8ea1e77..df9737c1fa 100644
--- a/ethereum/main.go
+++ b/ethereum/main.go
@@ -13,7 +13,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
- Version = "0.6.4"
+ Version = "0.6.5"
)
var logger = ethlog.NewLogger("CLI")
@@ -40,6 +40,12 @@ func main() {
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
db := utils.NewDatabase()
+ err := utils.DBSanityCheck(db)
+ if err != nil {
+ logger.Errorln(err)
+
+ os.Exit(1)
+ }
keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
@@ -70,6 +76,8 @@ func main() {
os.Exit(1)
}
+ fmt.Printf("RLP: %x\nstate: %x\nhash: %x\n", ethutil.Rlp(block), block.GetRoot(), block.Hash())
+
// Leave the Println. This needs clean output for piping
fmt.Printf("%s\n", block.State().Dump())
diff --git a/javascript/javascript_runtime.go b/javascript/javascript_runtime.go
index c794c32a8a..ffc672a63a 100644
--- a/javascript/javascript_runtime.go
+++ b/javascript/javascript_runtime.go
@@ -42,7 +42,7 @@ func (jsre *JSRE) LoadExtFile(path string) {
}
func (jsre *JSRE) LoadIntFile(file string) {
- assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal", "assets", "ext")
+ assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist", "assets", "ext")
jsre.LoadExtFile(path.Join(assetPath, file))
}
diff --git a/javascript/types.go b/javascript/types.go
index afa0a41c64..53a2977a82 100644
--- a/javascript/types.go
+++ b/javascript/types.go
@@ -88,6 +88,10 @@ func (self *JSEthereum) GetStateObject(addr string) otto.Value {
return self.toVal(&JSStateObject{ethpipe.NewJSObject(self.JSPipe.World().SafeGet(ethutil.Hex2Bytes(addr))), self})
}
+func (self *JSEthereum) Peers() otto.Value {
+ return self.toVal(self.JSPipe.Peers())
+}
+
func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
r, err := self.JSPipe.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
if err != nil {
diff --git a/ethereal/assets/back.png b/mist/assets/back.png
similarity index 100%
rename from ethereal/assets/back.png
rename to mist/assets/back.png
diff --git a/mist/assets/browser.png b/mist/assets/browser.png
new file mode 100644
index 0000000000..1d7348170f
Binary files /dev/null and b/mist/assets/browser.png differ
diff --git a/ethereal/assets/bug.png b/mist/assets/bug.png
similarity index 100%
rename from ethereal/assets/bug.png
rename to mist/assets/bug.png
diff --git a/ethereal/assets/close.png b/mist/assets/close.png
similarity index 100%
rename from ethereal/assets/close.png
rename to mist/assets/close.png
diff --git a/mist/assets/debugger/debugger.qml b/mist/assets/debugger/debugger.qml
new file mode 100644
index 0000000000..8d54b5b5d0
--- /dev/null
+++ b/mist/assets/debugger/debugger.qml
@@ -0,0 +1,435 @@
+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
+
+ApplicationWindow {
+ id: win
+ visible: false
+ title: "IceCREAM"
+ minimumWidth: 1280
+ minimumHeight: 700
+ width: 1290
+ height: 750
+
+ property alias codeText: codeEditor.text
+ property alias dataText: rawDataField.text
+
+ onClosing: {
+ dbg.Stop()
+ }
+
+ menuBar: MenuBar {
+ Menu {
+ title: "Edit"
+ MenuItem {
+ text: "Focus code"
+ shortcut: "Ctrl+1"
+ onTriggered: {
+ codeEditor.focus = true
+ }
+ }
+ MenuItem {
+ text: "Focus data"
+ shortcut: "Ctrl+2"
+ onTriggered: {
+ rawDataField.focus = true
+ }
+ }
+
+ MenuItem {
+ text: "Command"
+ shortcut: "Ctrl+l"
+ onTriggered: {
+ dbgCommand.focus = true
+ }
+ }
+ }
+
+ Menu {
+ title: "Debugger"
+ MenuItem {
+ text: "Run"
+ shortcut: "Ctrl+r"
+ onTriggered: debugCurrent()
+ }
+
+ MenuItem {
+ text: "Stop"
+ onTriggered: dbp.stop()
+ }
+
+ MenuSeparator {}
+
+ MenuItem {
+ text: "Next"
+ shortcut: "Ctrl+n"
+ onTriggered: dbg.next()
+ }
+
+ MenuItem {
+ text: "Continue"
+ shortcut: "Ctrl+g"
+ onTriggered: dbg.continue()
+ }
+ }
+ }
+
+
+ SplitView {
+ anchors.fill: parent
+ property var asmModel: ListModel {
+ id: asmModel
+ }
+
+ TableView {
+ id: asmTableView
+ width: 200
+ headerVisible: false
+ TableViewColumn{ role: "value" ; title: "" ; width: asmTableView.width - 2 }
+ model: asmModel
+ /*
+ alternatingRowColors: false
+ itemDelegate: Item {
+ Rectangle {
+ anchors.fill: parent
+ color: "#DDD"
+ Text {
+ anchors {
+ left: parent.left
+ right: parent.right
+ leftMargin: 10
+ verticalCenter: parent.verticalCenter
+ }
+ color: "#333"
+ elide: styleData.elideMode
+ text: styleData.value
+ font.pixelSize: 11
+ MouseArea {
+ acceptedButtons: Qt.LeftButton
+ anchors.fill: parent
+ onClicked: {
+ mouse.accepted = true
+ }
+ }
+ }
+ }
+ }
+ */
+ }
+
+ Rectangle {
+ color: "#00000000"
+ anchors.left: asmTableView.right
+ anchors.right: parent.right
+ SplitView {
+ orientation: Qt.Vertical
+ anchors.fill: parent
+
+ Rectangle {
+ color: "#00000000"
+ height: 330
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ TextArea {
+ id: codeEditor
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: settings.left
+ focus: true
+
+ /*
+ Timer {
+ id: compileTimer
+ interval: 500 ; running: true ; repeat: true
+ onTriggered: {
+ dbg.autoComp(codeEditor.text)
+ }
+ }
+ */
+ }
+
+ Column {
+ id: settings
+ spacing: 5
+ width: 300
+ height: parent.height
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ Label {
+ text: "Arbitrary data"
+ }
+ TextArea {
+ id: rawDataField
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 150
+ }
+
+ Label {
+ text: "Amount"
+ }
+ TextField {
+ id: txValue
+ width: 200
+ placeholderText: "Amount"
+ validator: RegExpValidator { regExp: /\d*/ }
+ }
+ Label {
+ text: "Amount of gas"
+ }
+ TextField {
+ id: txGas
+ width: 200
+ validator: RegExpValidator { regExp: /\d*/ }
+ text: "10000"
+ placeholderText: "Gas"
+ }
+ Label {
+ text: "Gas price"
+ }
+ TextField {
+ id: txGasPrice
+ width: 200
+ placeholderText: "Gas price"
+ text: "1000000000000"
+ validator: RegExpValidator { regExp: /\d*/ }
+ }
+ }
+ }
+
+ SplitView {
+ orientation: Qt.Vertical
+ id: inspectorPane
+ height: 500
+
+ SplitView {
+ orientation: Qt.Horizontal
+ height: 150
+
+ TableView {
+ id: stackTableView
+ property var stackModel: ListModel {
+ id: stackModel
+ }
+ height: parent.height
+ width: 300
+ TableViewColumn{ role: "value" ; title: "Local VM stack" ; width: stackTableView.width - 2 }
+ model: stackModel
+ }
+
+ TableView {
+ id: memoryTableView
+ property var memModel: ListModel {
+ id: memModel
+ }
+ height: parent.height
+ width: parent.width - stackTableView.width
+ TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50 }
+ TableViewColumn{ role: "value" ; title: "Memory" ; width: 650 }
+ model: memModel
+ }
+ }
+
+ Rectangle {
+ height: 100
+ width: parent.width
+ TableView {
+ id: storageTableView
+ property var memModel: ListModel {
+ id: storageModel
+ }
+ height: parent.height
+ width: parent.width
+ TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2 - 1}
+ TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2 - 1}
+ model: storageModel
+ }
+ }
+
+ Rectangle {
+ height: 200
+ width: parent.width * 0.66
+ TableView {
+ id: logTableView
+ property var logModel: ListModel {
+ id: logModel
+ }
+ height: parent.height
+ width: parent.width
+ TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width - 2 }
+ model: logModel
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ function exec() {
+ dbg.execCommand(dbgCommand.text);
+ dbgCommand.text = "";
+ }
+ statusBar: StatusBar {
+ height: 30
+
+
+ TextField {
+ id: dbgCommand
+ y: 1
+ x: asmTableView.width
+ width: 500
+ placeholderText: "Debugger (type 'help')"
+ Keys.onReturnPressed: {
+ exec()
+ }
+ }
+
+ RowLayout {
+ anchors.left: dbgCommand.right
+ anchors.leftMargin: 10
+ spacing: 5
+ y: parent.height / 2 - this.height / 2
+
+ Text {
+ objectName: "stackFrame"
+ font.pixelSize: 10
+ text: "stack ptr: 0"
+ }
+
+ Text {
+ objectName: "stackSize"
+ font.pixelSize: 10
+ text: "stack size: 0"
+ }
+
+ Text {
+ objectName: "memSize"
+ font.pixelSize: 10
+ text: "mem size: 0"
+ }
+ }
+ }
+
+ toolBar: ToolBar {
+ height: 30
+ RowLayout {
+ spacing: 10
+
+ Button {
+ property var enabled: true
+ id: debugStart
+ onClicked: {
+ debugCurrent()
+ }
+ text: "Debug"
+ }
+
+ Button {
+ property var enabled: true
+ id: debugNextButton
+ onClicked: {
+ dbg.next()
+ }
+ text: "Next"
+ }
+
+ Button {
+ id: debugContinueButton
+ onClicked: {
+ dbg.continue()
+ }
+ text: "Continue"
+ }
+ }
+
+
+ ComboBox {
+ id: snippets
+ anchors.right: parent.right
+ model: ListModel {
+ ListElement { text: "Snippets" ; value: "" }
+ ListElement { text: "Call Contract" ; value: "var[2] in;\nvar ret;\n\nin[0] = \"arg1\"\nin[1] = 0xdeadbeef\n\nvar success = call(0x0c542ddea93dae0c2fcb2cf175f03ad80d6be9a0, 0, 7000, in, ret)\n\nreturn ret" }
+ }
+ onCurrentIndexChanged: {
+ if(currentIndex != 0) {
+ var code = snippets.model.get(currentIndex).value;
+ codeEditor.insert(codeEditor.cursorPosition, code)
+ }
+ }
+ }
+
+ }
+
+ function debugCurrent() {
+ dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text)
+ }
+
+ function setAsm(asm) {
+ asmModel.append({asm: asm})
+ }
+
+ function clearAsm() {
+ asmModel.clear()
+ }
+
+ function setInstruction(num) {
+ asmTableView.selection.clear()
+ asmTableView.selection.select(num)
+ asmTableView.positionViewAtRow(num, ListView.Center)
+ }
+
+ function setMem(mem) {
+ memModel.append({num: mem.num, value: mem.value})
+ }
+ function clearMem(){
+ memModel.clear()
+ }
+
+ function setStack(stack) {
+ stackModel.append({value: stack})
+ }
+ function addDebugMessage(message){
+ debuggerLog.append({value: message})
+ }
+
+ function clearStack() {
+ stackModel.clear()
+ }
+
+ function clearStorage() {
+ storageModel.clear()
+ }
+
+ function setStorage(storage) {
+ storageModel.append({key: storage.key, value: storage.value})
+ }
+
+ function setLog(msg) {
+ // Remove first item once we've reached max log items
+ if(logModel.count > 250) {
+ logModel.remove(0)
+ }
+
+ if(msg.len != 0) {
+ if(logTableView.flickableItem.atYEnd) {
+ logModel.append({message: msg})
+ logTableView.positionViewAtRow(logTableView.rowCount - 1, ListView.Contain)
+ } else {
+ logModel.append({message: msg})
+ }
+ }
+ }
+
+ function clearLog() {
+ logModel.clear()
+ }
+}
diff --git a/ethereal/assets/ext/big.js b/mist/assets/ext/big.js
similarity index 100%
rename from ethereal/assets/ext/big.js
rename to mist/assets/ext/big.js
diff --git a/ethereal/assets/ext/ethereum.js b/mist/assets/ext/ethereum.js
similarity index 100%
rename from ethereal/assets/ext/ethereum.js
rename to mist/assets/ext/ethereum.js
diff --git a/mist/assets/ext/filter.js b/mist/assets/ext/filter.js
new file mode 100644
index 0000000000..c237062496
--- /dev/null
+++ b/mist/assets/ext/filter.js
@@ -0,0 +1,49 @@
+var ethx = {
+ prototype: Object,
+
+ watch: function(options) {
+ return new Filter(options);
+ },
+
+ note: function() {
+ var args = Array.prototype.slice.call(arguments, 0);
+ var o = []
+ for(var i = 0; i < args.length; i++) {
+ o.push(args[i].toString())
+ }
+
+ eth.notef(o);
+ },
+};
+
+var Filter = function(options) {
+ this.callbacks = [];
+ this.options = options;
+
+ if(options === "chain") {
+ this.id = eth.newFilterString(options);
+ } else if(typeof options === "object") {
+ this.id = eth.newFilter(options);
+ }
+};
+
+Filter.prototype.changed = function(callback) {
+ this.callbacks.push(callback);
+
+ var self = this;
+ messages.connect(function(messages, id) {
+ if(id == self.id) {
+ for(var i = 0; i < self.callbacks.length; i++) {
+ self.callbacks[i].call(self, messages);
+ }
+ }
+ });
+};
+
+Filter.prototype.uninstall = function() {
+ eth.uninstallFilter(this.id)
+}
+
+Filter.prototype.messages = function() {
+ return eth.messages(this.id)
+}
diff --git a/ethereal/assets/ext/home.html b/mist/assets/ext/home.html
similarity index 100%
rename from ethereal/assets/ext/home.html
rename to mist/assets/ext/home.html
diff --git a/mist/assets/ext/html_messaging.js b/mist/assets/ext/html_messaging.js
new file mode 100644
index 0000000000..3c67c77ea8
--- /dev/null
+++ b/mist/assets/ext/html_messaging.js
@@ -0,0 +1,481 @@
+// The magic return variable. The magic return variable will be set during the execution of the QML call.
+(function(window) {
+ function message(type, data) {
+ document.title = JSON.stringify({type: type, data: data});
+
+ return window.____returnData;
+ }
+
+ 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(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: "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 "1000000000000"
+ }
+ });
+
+ 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++;
+
+ 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];
+ }
+ }
+ }
+ }
+})(this);
diff --git a/mist/assets/ext/http.js b/mist/assets/ext/http.js
new file mode 100644
index 0000000000..725ce8e6b0
--- /dev/null
+++ b/mist/assets/ext/http.js
@@ -0,0 +1,13 @@
+// this function is included locally, but you can also include separately via a header definition
+function request(url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = (function(req) {
+ return function() {
+ if(req.readyState === 4) {
+ callback(req);
+ }
+ }
+ })(xhr);
+ xhr.open('GET', url, true);
+ xhr.send('');
+}
diff --git a/mist/assets/ext/pre.js b/mist/assets/ext/pre.js
new file mode 100644
index 0000000000..f298fe9a13
--- /dev/null
+++ b/mist/assets/ext/pre.js
@@ -0,0 +1,3 @@
+if(typeof(Promise) === "undefined") {
+ window.Promise = Q.Promise;
+}
diff --git a/mist/assets/ext/q.js b/mist/assets/ext/q.js
new file mode 100644
index 0000000000..23c4245eec
--- /dev/null
+++ b/mist/assets/ext/q.js
@@ -0,0 +1,1909 @@
+// 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