diff --git a/ethereum/flags.go b/ethereum/flags.go
index c488e631431daeb1a5379a5da2a33a4b20597b4d..58220f4e6bc6988dcaf466c3f2db89997360613f 100644
--- a/ethereum/flags.go
+++ b/ethereum/flags.go
@@ -10,36 +10,41 @@ import (
 	"github.com/ethereum/eth-go/ethlog"
 )
 
-var Identifier string
-var KeyRing string
-var DiffTool bool
-var DiffType string
-var KeyStore string
-var StartRpc bool
-var RpcPort int
-var UseUPnP bool
-var OutboundPort string
-var ShowGenesis bool
-var AddPeer string
-var MaxPeer int
-var GenAddr bool
-var UseSeed bool
-var SecretFile string
-var ExportDir string
-var NonInteractive bool
-var Datadir string
-var LogFile string
-var ConfigFile string
-var DebugFile string
-var LogLevel int
-var Dump bool
-var DumpHash string
-var DumpNumber int
+var (
+	Identifier      string
+	KeyRing         string
+	DiffTool        bool
+	DiffType        string
+	KeyStore        string
+	StartRpc        bool
+	StartWebSockets bool
+	RpcPort         int
+	UseUPnP         bool
+	OutboundPort    string
+	ShowGenesis     bool
+	AddPeer         string
+	MaxPeer         int
+	GenAddr         bool
+	UseSeed         bool
+	SecretFile      string
+	ExportDir       string
+	NonInteractive  bool
+	Datadir         string
+	LogFile         string
+	ConfigFile      string
+	DebugFile       string
+	LogLevel        int
+	Dump            bool
+	DumpHash        string
+	DumpNumber      int
+)
 
 // flags specific to cli client
-var StartMining bool
-var StartJsConsole bool
-var InputFile string
+var (
+	StartMining    bool
+	StartJsConsole bool
+	InputFile      string
+)
 
 func defaultDataDir() string {
 	usr, _ := user.Current()
@@ -62,6 +67,7 @@ func Init() {
 	flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
 	flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
 	flag.BoolVar(&StartRpc, "rpc", false, "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")
diff --git a/ethereum/main.go b/ethereum/main.go
index 6521188ff62b78d5d247ca69ceefb22094e30438..0f0df20bbd8d8230fed16d02154cda089e7e274a 100644
--- a/ethereum/main.go
+++ b/ethereum/main.go
@@ -103,6 +103,10 @@ func main() {
 		utils.StartRpc(ethereum, RpcPort)
 	}
 
+	if StartWebSockets {
+		utils.StartWebSockets(ethereum)
+	}
+
 	utils.StartEthereum(ethereum, UseSeed)
 
 	// this blocks the thread
diff --git a/mist/assets/ext/html_messaging.js b/mist/assets/ext/html_messaging.js
index 1f941814831e95493140aaf5d0ad07e60cc7535a..91310e998eceb7e51123b42141703aa6f6a5f25c 100644
--- a/mist/assets/ext/html_messaging.js
+++ b/mist/assets/ext/html_messaging.js
@@ -1,9 +1,8 @@
 // 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;
+	var Promise = window.Promise;
+	if(typeof(Promise) === "undefined") {
+		var Promise = Q.Promise;
 	}
 
 	function isPromise(o) {
@@ -446,6 +445,7 @@
 		}
 	});
 
+
 	var g_seed = 1;
 	function postData(data, cb) {
 		data._seed = g_seed;
@@ -459,24 +459,6 @@
 
 		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];
-				}
-			}
-		}
+		window._messagingAdapter.call(this, JSON.stringify(data))
 	}
 })(this);
diff --git a/mist/assets/ext/pre.js b/mist/assets/ext/pre.js
deleted file mode 100644
index f298fe9a138269beca1447f7b336252a20e994c3..0000000000000000000000000000000000000000
--- a/mist/assets/ext/pre.js
+++ /dev/null
@@ -1,3 +0,0 @@
-if(typeof(Promise) === "undefined") {
-	window.Promise = Q.Promise;
-}
diff --git a/mist/assets/ext/qt_messaging_adapter.js b/mist/assets/ext/qt_messaging_adapter.js
new file mode 100644
index 0000000000000000000000000000000000000000..ff69761777413960a8115f68f18c10e4ea91909a
--- /dev/null
+++ b/mist/assets/ext/qt_messaging_adapter.js
@@ -0,0 +1,21 @@
+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/mist/assets/qml/main.qml b/mist/assets/qml/main.qml
index 0ee063f179dd0d7127f719d85c13e765092be469..3d9204ce871246ae16536e025b4c6f36b5575917 100644
--- a/mist/assets/qml/main.qml
+++ b/mist/assets/qml/main.qml
@@ -10,894 +10,902 @@ import "../ext/filter.js" as Eth
 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
-
-    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
-    }
-
-    function copyToClipboard(text) {
-        copyElementHax.text = text
-        copyElementHax.selectAll()
-        copyElementHax.copy()
-    }
-
-    // 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/transaction.qml", {noAdd: true, close: false, section: "legacy"});
-        addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
-        addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"});
-        addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"});
-        addPlugin("./views/javascript.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();
-    }
-
-    function addViews(view, path, options) {
-        var views = mainSplit.addComponent(view, options)
-        views.menuItem.path = path
-
-        mainSplit.views.push(views);
-
-        if(!options.noAdd) {
-            gui.addPlugin(path)
-        }
-
-        return views
-    }
-
-    function addPlugin(path, options) {
-        try {
-            if(typeof(path) === "string" && /^https?/.test(path)) {
-                console.log('load http')
-                Http.request(path, function(o) {
-                    if(o.status === 200) {
-                        var view = Qt.createQmlObject(o.responseText, mainView, path)
-                        addViews(view, path, options)
-                    }
-                })
-
-                return
-            }
-
-            var component = Qt.createComponent(path);
-            if(component.status != Component.Ready) {
-                if(component.status == Component.Error) {
-                    ethx.note("error: ", component.errorString());
-                }
-
-                return
-            }
-
-            var view = mainView.createView(component, options)
-            var views = addViews(view, path, options)
-
-            return views
-        } catch(e) {
-            ethx.note(e)
-        }
-    }
-
-    menuBar: 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, {close: 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 {
-                iconSource: "../icecream.png"
-                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
-                }
-            }
-        }
-
-        Menu {
-            title: "GLOBAL SHORTCUTS"
-            visible: false
-            MenuItem {
-                visible: false
-                shortcut: "Ctrl+l"
-                onTriggered: {
-                    url.focus = true
-                }
-            }
-        }
-    }
-
-    statusBar: StatusBar {
-        height: 32
-	id: statusBar
-        RowLayout {
-            Button {
-                id: miningButton
-                text: "Start Mining"
-                onClicked: {
-                    gui.toggleMining()
-                }
-            }
-
-            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: downloadIndicator
-	    value: 0
-            visible: true
-            objectName: "downloadIndicator"
-            y: 3
-	    x: statusBar.width / 2 - this.width / 2
-            width: 160
-        }
-
-
-        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.setSelection(false)
-            }
-            view.visible = true
-
-            //menu.border.color = "#CCCCCC"
-            //menu.color = "#FFFFFFFF"
-            menu.setSelection(true)
-        }
-
-        function addComponent(view, 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: 210
-             Layout.maximumWidth: 210
-             anchors.top: parent.top
-             color: "#ececec"
-
-             Component {
-                 id: menuItemTemplate
-                 Rectangle {
-                     id: menuItem
-                     property var view;
-                     property var path;
-                     property var closable;
-
-                     property alias title: label.text
-                     property alias icon: icon.source
-                     property alias secondaryTitle: secondary.text
-                     function setSelection(on) {
-                         sel.visible = on
-                     }
-
-                     width: 206
-                     height: 28
-                     color: "#00000000"
-
-                     anchors {
-                         left: parent.left
-                         leftMargin: 4
-                     }
-
-                     Rectangle {
-                         id: sel
-                         visible: false
-                         anchors.fill: parent
-                         color: "#00000000"
-                         Rectangle {
-                             id: r
-                             anchors.fill: parent
-                             border.color: "#CCCCCC"
-                             border.width: 1
-                             radius: 5
-                             color: "#FFFFFFFF"
-                         }
-                         Rectangle {
-                             anchors {
-                                 top: r.top
-                                 bottom: r.bottom
-                                 right: r.right
-                             }
-                             width: 10
-                             color: "#FFFFFFFF"
-
-                             Rectangle {
-                                 anchors {
-                                     left: parent.left
-                                     right: parent.right
-                                     top: parent.top
-                                 }
-                                 height: 1
-                                 color: "#CCCCCC"
-                             }
-
-                             Rectangle {
-                                 anchors {
-                                     left: parent.left
-                                     right: parent.right
-                                     bottom: parent.bottom
-                                 }
-                                 height: 1
-                                 color: "#CCCCCC"
-                             }
-                         }
-                     }
-
-                     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.closable) { return; }
-
-                         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
-                 comp.closable = options.close;
-
-                 return comp
-             }
-
-             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 {
-              anchors.right: parent.right
-              anchors.left: menu.right
-              anchors.bottom: parent.bottom
-              anchors.top: parent.top
-              color: "#00000000"
-
-              Rectangle {
-                  id: urlPane
-                  height: 40
-                  color: "#00000000"
-                  anchors {
-                      left: parent.left
-                      right: parent.right
-                      leftMargin: 5
-                      rightMargin: 5
-                      top: parent.top
-                      topMargin: 5
-                  }
-                  TextField {
-                      id: url
-                      objectName: "url"
-                      placeholderText: "DApp URL"
-                      anchors {
-                          left: parent.left
-                          right: parent.right
-                          top: parent.top
-                          topMargin: 5
-                          rightMargin: 5
-                          leftMargin: 5
-                      }
-
-                      Keys.onReturnPressed: {
-			      if(/^https?/.test(this.text)) {
-				      root.browser.view.open(this.text);
-				      mainSplit.setView(root.browser.view, root.browser.menuItem);
-			      } else {
-				      addPlugin(this.text, {close: true, section: "apps"})
-			      }
-                      }
-                  }
-
-              }
-
-              // Border
-              Rectangle {
-                  id: divider
-                  anchors {
-                      left: parent.left
-                      right: parent.right
-                      top: urlPane.bottom
-                  }
-                  z: -1
-                  height: 1
-                  color: "#CCCCCC"
-              }
-
-              Rectangle {
-                  id: mainView
-                  color: "#00000000"
-                  anchors.right: parent.right
-                  anchors.left: parent.left
-                  anchors.bottom: parent.bottom
-                  anchors.top: divider.bottom
-
-                  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, {close: 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, caps: peer.caps})
-        }
-
-        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" }
-		     TableViewColumn{width: 80;  role: "caps" ; title: "Capabilities" }
-                 }
-             }
-         }
-
-         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
-                 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"
-             }
-         }
-
-         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: 300
-             maximumWidth: 300
-             maximumHeight: 50
-             minimumHeight: 50
-             title: "Connect to peer"
-
-             ComboBox {
-                 id: addrField
-                 anchors.verticalCenter: parent.verticalCenter
-                 anchors.left: parent.left
-                 anchors.right: addPeerButton.left
-                 anchors.leftMargin: 10
-                 anchors.rightMargin: 10
-                 onAccepted: {
-                     eth.connectToPeer(addrField.currentText)
-                     addPeerWin.visible = false
-                 }
-
-                 editable: true
-                 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-6.ethdev.com:30303"})
-                 }
-             }
-
-             Button {
-                 id: addPeerButton
-                 anchors.right: parent.right
-                 anchors.verticalCenter: parent.verticalCenter
-                 anchors.rightMargin: 10
-                 text: "Add"
-                 onClicked: {
-                     eth.connectToPeer(addrField.currentText)
-                     addPeerWin.visible = false
-                 }
-             }
-             Component.onCompleted: {
-                 addrField.focus = true
-             }
-         }
+	id: root
+
+	property alias miningButtonText: miningButton.text
+	property var ethx : Eth.ethx
+	property var browser
+
+	width: 1200
+	height: 820
+	minimumHeight: 300
+
+	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
+	}
+
+	function copyToClipboard(text) {
+		copyElementHax.text = text
+		copyElementHax.selectAll()
+		copyElementHax.copy()
+	}
+
+	// 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/transaction.qml", {noAdd: true, close: false, section: "legacy"});
+		addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
+		addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"});
+		addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"});
+		addPlugin("./views/javascript.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();
+	}
+
+	function addViews(view, path, options) {
+		var views = mainSplit.addComponent(view, options)
+		views.menuItem.path = path
+
+		mainSplit.views.push(views);
+
+		if(!options.noAdd) {
+			gui.addPlugin(path)
+		}
+
+		return views
+	}
+
+	function addPlugin(path, options) {
+		try {
+			if(typeof(path) === "string" && /^https?/.test(path)) {
+				console.log('load http')
+				Http.request(path, function(o) {
+					if(o.status === 200) {
+						var view = Qt.createQmlObject(o.responseText, mainView, path)
+						addViews(view, path, options)
+					}
+				})
+
+				return
+			}
+
+			var component = Qt.createComponent(path);
+			if(component.status != Component.Ready) {
+				if(component.status == Component.Error) {
+					ethx.note("error: ", component.errorString());
+				}
+
+				return
+			}
+
+			var view = mainView.createView(component, options)
+			var views = addViews(view, path, options)
+
+			return views
+		} catch(e) {
+			ethx.note(e)
+		}
+	}
+
+	menuBar: 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, {close: 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 {
+				iconSource: "../icecream.png"
+				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
+				}
+			}
+		}
+
+		Menu {
+			title: "GLOBAL SHORTCUTS"
+			visible: false
+			MenuItem {
+				visible: false
+				shortcut: "Ctrl+l"
+				onTriggered: {
+					url.focus = true
+				}
+			}
+		}
+	}
+
+	statusBar: StatusBar {
+		height: 32
+		id: statusBar
+		RowLayout {
+			Button {
+				id: miningButton
+				text: "Start Mining"
+				onClicked: {
+					gui.toggleMining()
+				}
+			}
+
+			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: downloadIndicator
+			value: 0
+			objectName: "downloadIndicator"
+			y: 3
+			x: statusBar.width / 2 - this.width / 2
+			width: 160
+		}
+
+		Label {
+			objectName: "downloadLabel"
+			y: 7
+			anchors.left: downloadIndicator.right
+			anchors.leftMargin: 5
+			font.pixelSize: 10
+			text: "0 / 0"
+		}
+
+
+		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.setSelection(false)
+			}
+			view.visible = true
+
+			//menu.border.color = "#CCCCCC"
+			//menu.color = "#FFFFFFFF"
+			menu.setSelection(true)
+		}
+
+		function addComponent(view, 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: 210
+			 Layout.maximumWidth: 210
+			 anchors.top: parent.top
+			 color: "#ececec"
+
+			 Component {
+				 id: menuItemTemplate
+				 Rectangle {
+					 id: menuItem
+					 property var view;
+					 property var path;
+					 property var closable;
+
+					 property alias title: label.text
+					 property alias icon: icon.source
+					 property alias secondaryTitle: secondary.text
+					 function setSelection(on) {
+						 sel.visible = on
+					 }
+
+					 width: 206
+					 height: 28
+					 color: "#00000000"
+
+					 anchors {
+						 left: parent.left
+						 leftMargin: 4
+					 }
+
+					 Rectangle {
+						 id: sel
+						 visible: false
+						 anchors.fill: parent
+						 color: "#00000000"
+						 Rectangle {
+							 id: r
+							 anchors.fill: parent
+							 border.color: "#CCCCCC"
+							 border.width: 1
+							 radius: 5
+							 color: "#FFFFFFFF"
+						 }
+						 Rectangle {
+							 anchors {
+								 top: r.top
+								 bottom: r.bottom
+								 right: r.right
+							 }
+							 width: 10
+							 color: "#FFFFFFFF"
+
+							 Rectangle {
+								 anchors {
+									 left: parent.left
+									 right: parent.right
+									 top: parent.top
+								 }
+								 height: 1
+								 color: "#CCCCCC"
+							 }
+
+							 Rectangle {
+								 anchors {
+									 left: parent.left
+									 right: parent.right
+									 bottom: parent.bottom
+								 }
+								 height: 1
+								 color: "#CCCCCC"
+							 }
+						 }
+					 }
+
+					 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.closable) { return; }
+
+						 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
+				 comp.closable = options.close;
+
+				 return comp
+			 }
+
+			 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 {
+			  anchors.right: parent.right
+			  anchors.left: menu.right
+			  anchors.bottom: parent.bottom
+			  anchors.top: parent.top
+			  color: "#00000000"
+
+			  Rectangle {
+				  id: urlPane
+				  height: 40
+				  color: "#00000000"
+				  anchors {
+					  left: parent.left
+					  right: parent.right
+					  leftMargin: 5
+					  rightMargin: 5
+					  top: parent.top
+					  topMargin: 5
+				  }
+				  TextField {
+					  id: url
+					  objectName: "url"
+					  placeholderText: "DApp URL"
+					  anchors {
+						  left: parent.left
+						  right: parent.right
+						  top: parent.top
+						  topMargin: 5
+						  rightMargin: 5
+						  leftMargin: 5
+					  }
+
+					  Keys.onReturnPressed: {
+						  if(/^https?/.test(this.text)) {
+							  root.browser.view.open(this.text);
+							  mainSplit.setView(root.browser.view, root.browser.menuItem);
+						  } else {
+							  addPlugin(this.text, {close: true, section: "apps"})
+						  }
+					  }
+				  }
+
+			  }
+
+			  // Border
+			  Rectangle {
+				  id: divider
+				  anchors {
+					  left: parent.left
+					  right: parent.right
+					  top: urlPane.bottom
+				  }
+				  z: -1
+				  height: 1
+				  color: "#CCCCCC"
+			  }
+
+			  Rectangle {
+				  id: mainView
+				  color: "#00000000"
+				  anchors.right: parent.right
+				  anchors.left: parent.left
+				  anchors.bottom: parent.bottom
+				  anchors.top: divider.bottom
+
+				  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, {close: 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, caps: peer.caps})
+	    }
+
+	    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" }
+				     TableViewColumn{width: 80;  role: "caps" ; title: "Capabilities" }
+			     }
+		     }
+	     }
+
+	     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
+			     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"
+		     }
+	     }
+
+	     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: 300
+		     maximumWidth: 300
+		     maximumHeight: 50
+		     minimumHeight: 50
+		     title: "Connect to peer"
+
+		     ComboBox {
+			     id: addrField
+			     anchors.verticalCenter: parent.verticalCenter
+			     anchors.left: parent.left
+			     anchors.right: addPeerButton.left
+			     anchors.leftMargin: 10
+			     anchors.rightMargin: 10
+			     onAccepted: {
+				     eth.connectToPeer(addrField.currentText)
+				     addPeerWin.visible = false
+			     }
+
+			     editable: true
+			     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-6.ethdev.com:30303"})
+			     }
+		     }
+
+		     Button {
+			     id: addPeerButton
+			     anchors.right: parent.right
+			     anchors.verticalCenter: parent.verticalCenter
+			     anchors.rightMargin: 10
+			     text: "Add"
+			     onClicked: {
+				     eth.connectToPeer(addrField.currentText)
+				     addPeerWin.visible = false
+			     }
+		     }
+		     Component.onCompleted: {
+			     addrField.focus = true
+		     }
+	     }
      }
diff --git a/mist/assets/qml/webapp.qml b/mist/assets/qml/webapp.qml
index dde2984848e86000fe271b3f824042642e146c8a..09e6a83ad0c1bc7657524bb012dfb6f618710186 100644
--- a/mist/assets/qml/webapp.qml
+++ b/mist/assets/qml/webapp.qml
@@ -164,7 +164,7 @@ import "../ext/qml_messaging.js" as Messaging
 				experimental.preferences.javascriptEnabled: true
 				experimental.preferences.navigatorQtObjectEnabled: true
 				experimental.preferences.developerExtrasEnabled: true
-				experimental.userScripts: ["../ext/q.js", "../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"]
+				experimental.userScripts: ["../ext/qt_messaging_adapter.js", "../ext/q.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"]
 				experimental.onMessageReceived: {
 					console.log("[onMessageReceived]: ", message.data)
 					// TODO move to messaging.js
diff --git a/mist/gui.go b/mist/gui.go
index 45ef66624d0ef690e0f8fdb911ac5986ed939f7a..80d4a1fc3fd98226881a7fcf0a9b8d7e54015393 100644
--- a/mist/gui.go
+++ b/mist/gui.go
@@ -271,7 +271,8 @@ func (gui *Gui) loadAddressBook() {
 }
 
 func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
-	nameReg := ethpipe.New(gui.eth).World().Config().Get("NameReg")
+	pipe := ethpipe.New(gui.eth)
+	nameReg := pipe.World().Config().Get("NameReg")
 	addr := gui.address()
 
 	var inout string
@@ -282,14 +283,14 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
 	}
 
 	var (
-		ptx  = ethpipe.NewJSTx(tx)
+		ptx  = ethpipe.NewJSTx(tx, pipe.World().State())
 		send = nameReg.Storage(tx.Sender())
 		rec  = nameReg.Storage(tx.Recipient)
 		s, r string
 	)
 
 	if tx.CreatesContract() {
-		rec = nameReg.Storage(tx.CreationAddress())
+		rec = nameReg.Storage(tx.CreationAddress(pipe.World().State()))
 	}
 
 	if send.Len() != 0 {
@@ -301,7 +302,7 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
 		r = strings.Trim(rec.Str(), "\x00")
 	} else {
 		if tx.CreatesContract() {
-			r = ethutil.Bytes2Hex(tx.CreationAddress())
+			r = ethutil.Bytes2Hex(tx.CreationAddress(pipe.World().State()))
 		} else {
 			r = ethutil.Bytes2Hex(tx.Recipient)
 		}
@@ -466,13 +467,11 @@ func (gui *Gui) update() {
 				var (
 					pct      float64 = 1.0 / float64(chainLength) * float64(blockLength)
 					dlWidget         = gui.win.Root().ObjectByName("downloadIndicator")
+					dlLabel          = gui.win.Root().ObjectByName("downloadLabel")
 				)
-				if pct < 1.0 {
-					dlWidget.Set("visible", true)
-					dlWidget.Set("value", pct)
-				} else {
-					dlWidget.Set("visible", false)
-				}
+
+				dlWidget.Set("value", pct)
+				dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
 
 			case <-statsUpdateTicker.C:
 				gui.setStatsPane()
@@ -500,7 +499,7 @@ func (gui *Gui) setStatsPane() {
 	runtime.ReadMemStats(&memStats)
 
 	statsPane := gui.getObjectByName("statsPane")
-	statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.7 (%s) #######
+	statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.8 (%s) #######
 
 eth %d (p2p = %d)
 
diff --git a/utils/websockets.go b/utils/websockets.go
new file mode 100644
index 0000000000000000000000000000000000000000..e89331a98d6edac9a98efff24fbae9395f44c802
--- /dev/null
+++ b/utils/websockets.go
@@ -0,0 +1,161 @@
+package utils
+
+import (
+	"github.com/ethereum/eth-go"
+	"github.com/ethereum/eth-go/ethpipe"
+	"github.com/ethereum/eth-go/ethutil"
+	"github.com/ethereum/eth-go/websocket"
+)
+
+func args(v ...interface{}) []interface{} {
+	return v
+}
+
+type WebSocketServer struct {
+	ethereum        *eth.Ethereum
+	filterCallbacks map[int][]int
+}
+
+func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
+	return &WebSocketServer{eth, make(map[int][]int)}
+}
+
+func (self *WebSocketServer) Serv() {
+	pipe := ethpipe.NewJSPipe(self.ethereum)
+
+	wsServ := websocket.NewServer("/eth", ":40404")
+	wsServ.MessageFunc(func(c *websocket.Client, msg *websocket.Message) {
+		switch msg.Call {
+		case "compile":
+			data := ethutil.NewValue(msg.Args)
+			bcode, err := ethutil.Compile(data.Get(0).Str(), false)
+			if err != nil {
+				c.Write(args(nil, err.Error()), msg.Seed)
+			}
+
+			code := ethutil.Bytes2Hex(bcode)
+			c.Write(args(code, nil), msg.Seed)
+		case "getBlockByNumber":
+			args := msg.Arguments()
+
+			block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
+			c.Write(block, msg.Seed)
+
+		case "getKey":
+			c.Write(pipe.Key().PrivateKey, msg.Seed)
+		case "transact":
+			if mp, ok := msg.Args[0].(map[string]interface{}); ok {
+				object := mapToTxParams(mp)
+				c.Write(
+					args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])),
+					msg.Seed,
+				)
+
+			}
+		case "getCoinBase":
+			c.Write(pipe.CoinBase(), msg.Seed)
+
+		case "getIsListening":
+			c.Write(pipe.IsListening(), msg.Seed)
+
+		case "getIsMining":
+			c.Write(pipe.IsMining(), msg.Seed)
+
+		case "getPeerCoint":
+			c.Write(pipe.PeerCount(), msg.Seed)
+
+		case "getCountAt":
+			args := msg.Arguments()
+
+			c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Seed)
+
+		case "getCodeAt":
+			args := msg.Arguments()
+
+			c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Seed)
+
+		case "getBlockByHash":
+			args := msg.Arguments()
+
+			c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Seed)
+
+		case "getStorageAt":
+			args := msg.Arguments()
+
+			c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Seed)
+
+		case "getBalanceAt":
+			args := msg.Arguments()
+
+			c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Seed)
+
+		case "getSecretToAddress":
+			args := msg.Arguments()
+
+			c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Seed)
+
+		case "newFilter":
+		case "newFilterString":
+		case "messages":
+			// TODO
+		}
+
+	})
+
+	wsServ.Listen()
+}
+
+func StartWebSockets(eth *eth.Ethereum) {
+	sock := NewWebSocketServer(eth)
+	go sock.Serv()
+}
+
+// TODO This is starting to become a generic method. Move to utils
+func mapToTxParams(object map[string]interface{}) map[string]string {
+	// Default values
+	if object["from"] == nil {
+		object["from"] = ""
+	}
+	if object["to"] == nil {
+		object["to"] = ""
+	}
+	if object["value"] == nil {
+		object["value"] = ""
+	}
+	if object["gas"] == nil {
+		object["gas"] = ""
+	}
+	if object["gasPrice"] == nil {
+		object["gasPrice"] = ""
+	}
+
+	var dataStr string
+	var data []string
+	if str, ok := object["data"].(string); ok {
+		data = []string{str}
+	}
+
+	for _, str := range data {
+		if ethutil.IsHex(str) {
+			str = str[2:]
+
+			if len(str) != 64 {
+				str = ethutil.LeftPadString(str, 64)
+			}
+		} else {
+			str = ethutil.Bytes2Hex(ethutil.LeftPadBytes(ethutil.Big(str).Bytes(), 32))
+		}
+
+		dataStr += str
+	}
+	object["data"] = dataStr
+
+	conv := make(map[string]string)
+	for key, value := range object {
+		if v, ok := value.(string); ok {
+			conv[key] = v
+		}
+	}
+
+	return conv
+}