diff --git a/README.md b/README.md
index 2d4b128fc96310c29cf837b69894b441f481f3cf..8cdcfe2a6d2d9f98d375c69c406fe71f2cf69840 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 34fe01253d774f927df9ae7db971b1d4c180b804..0000000000000000000000000000000000000000
--- 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 5c1c03aada487c658ae0eb5c8bf6097d23291cb4..0000000000000000000000000000000000000000
--- 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 3e8a534e9b616eb79dad3fc0e3196630f3f0983f..0000000000000000000000000000000000000000
--- 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 90cc42a1fa45c0f64da4e0db3fb0c647075d8e9a..0000000000000000000000000000000000000000
--- 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: "<h2>Ethereal - Aitne</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>Viktor Trón<br>"
-		     }
-	     }
-
-	     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 ca686003672012e812ab7bb712552fe24e752544..0000000000000000000000000000000000000000
--- 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 5ed208411b17ec251afb38d673f6aa114345e031..c488e631431daeb1a5379a5da2a33a4b20597b4d 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 b7c8ea1e77fd36cddbfed9ffb42dd84706ba2eef..df9737c1fa0dd75c84f4c9bb87100677e3330e23 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 c794c32a8a6dbea94eb5b1fc61bf284618508098..ffc672a63a41cf08ce38ad10e3261e2e4f8a41ad 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 afa0a41c64e02aad43250176e207608fee418e34..53a2977a820b3442f19a6a7f866dd9b2f02caab4 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 0000000000000000000000000000000000000000..1d7348170f7cadb76a1314a1d4fdcb03ab1abdd9
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 0000000000000000000000000000000000000000..8d54b5b5d01f3a911494e84e0b89c2ef073712ad
--- /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: "<b>stack ptr</b>: 0"
+            }
+
+            Text {
+                objectName: "stackSize"
+                font.pixelSize: 10
+                text: "<b>stack size</b>: 0"
+            }
+
+            Text {
+                objectName: "memSize"
+                font.pixelSize: 10
+                text: "<b>mem size</b>: 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 0000000000000000000000000000000000000000..c237062496650147ad54f12736856df5c588c1ab
--- /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 0000000000000000000000000000000000000000..3c67c77ea838640f24d1f1e790f8aafd2206c04d
--- /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 0000000000000000000000000000000000000000..725ce8e6b02df04691447e1b9d26bcdff09e920c
--- /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 0000000000000000000000000000000000000000..f298fe9a138269beca1447f7b336252a20e994c3
--- /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 0000000000000000000000000000000000000000..23c4245eeccbc444e26cd20c243613ef20c5c911
--- /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 <script> tag, or a module
+    // using CommonJS and NodeJS or RequireJS module formats.  In
+    // Common/Node/RequireJS, the module exports the Q API and when
+    // executed as a simple <script>, it creates a Q global instead.
+
+    // Montage Require
+    if (typeof bootstrap === "function") {
+        bootstrap("promise", definition);
+
+    // CommonJS
+    } else if (typeof exports === "object" && typeof module === "object") {
+        module.exports = definition();
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+        define(definition);
+
+    // SES (Secure EcmaScript)
+    } else if (typeof ses !== "undefined") {
+        if (!ses.ok()) {
+            return;
+        } else {
+            ses.makeQ = definition;
+        }
+
+    // <script>
+    } else {
+        Q = definition();
+    }
+
+})(function () {
+"use strict";
+
+var hasStacks = false;
+try {
+    throw new Error();
+} catch (e) {
+    hasStacks = !!e.stack;
+}
+
+// All code after this point will be filtered from stack traces reported
+// by Q.
+var qStartingLine = captureLine();
+var qFileName;
+
+// shims
+
+// used for fallback in "allResolved"
+var noop = function () {};
+
+// Use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick =(function () {
+    // linked list of tasks (single, with head node)
+    var head = {task: void 0, next: null};
+    var tail = head;
+    var flushing = false;
+    var requestTick = void 0;
+    var isNodeJS = false;
+
+    function flush() {
+        /* jshint loopfunc: true */
+
+        while (head.next) {
+            head = head.next;
+            var task = head.task;
+            head.task = void 0;
+            var domain = head.domain;
+
+            if (domain) {
+                head.domain = void 0;
+                domain.enter();
+            }
+
+            try {
+                task();
+
+            } catch (e) {
+                if (isNodeJS) {
+                    // In node, uncaught exceptions are considered fatal errors.
+                    // Re-throw them synchronously to interrupt flushing!
+
+                    // Ensure continuation if the uncaught exception is suppressed
+                    // listening "uncaughtException" events (as domains does).
+                    // Continue in next event to avoid tick recursion.
+                    if (domain) {
+                        domain.exit();
+                    }
+                    setTimeout(flush, 0);
+                    if (domain) {
+                        domain.enter();
+                    }
+
+                    throw e;
+
+                } else {
+                    // In browsers, uncaught exceptions are not fatal.
+                    // Re-throw them asynchronously to avoid slow-downs.
+                    setTimeout(function() {
+                       throw e;
+                    }, 0);
+                }
+            }
+
+            if (domain) {
+                domain.exit();
+            }
+        }
+
+        flushing = false;
+    }
+
+    nextTick = function (task) {
+        tail = tail.next = {
+            task: task,
+            domain: isNodeJS && process.domain,
+            next: null
+        };
+
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+
+    if (typeof process !== "undefined" && process.nextTick) {
+        // Node.js before 0.9. Note that some fake-Node environments, like the
+        // Mocha test runner, introduce a `process` global without a `nextTick`.
+        isNodeJS = true;
+
+        requestTick = function () {
+            process.nextTick(flush);
+        };
+
+    } else if (typeof setImmediate === "function") {
+        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
+        if (typeof window !== "undefined") {
+            requestTick = setImmediate.bind(window, flush);
+        } else {
+            requestTick = function () {
+                setImmediate(flush);
+            };
+        }
+
+    } else if (typeof MessageChannel !== "undefined") {
+        // modern browsers
+        // http://www.nonblocking.io/2011/06/windownexttick.html
+        var channel = new MessageChannel();
+        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
+        // working message ports the first time a page loads.
+        channel.port1.onmessage = function () {
+            requestTick = requestPortTick;
+            channel.port1.onmessage = flush;
+            flush();
+        };
+        var requestPortTick = function () {
+            // Opera requires us to provide a message payload, regardless of
+            // whether we use it.
+            channel.port2.postMessage(0);
+        };
+        requestTick = function () {
+            setTimeout(flush, 0);
+            requestPortTick();
+        };
+
+    } else {
+        // old browsers
+        requestTick = function () {
+            setTimeout(flush, 0);
+        };
+    }
+
+    return nextTick;
+})();
+
+// Attempt to make generics safe in the face of downstream
+// modifications.
+// There is no situation where this is necessary.
+// If you need a security guarantee, these primordials need to be
+// deeply frozen anyway, and if you don’t need a security guarantee,
+// this is just plain paranoid.
+// However, this **might** have the nice side-effect of reducing the size of
+// the minified code by reducing x.call() to merely x()
+// See Mark Miller’s explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+var call = Function.call;
+function uncurryThis(f) {
+    return function () {
+        return call.apply(f, arguments);
+    };
+}
+// This is equivalent, but slower:
+// uncurryThis = Function_bind.bind(Function_bind.call);
+// http://jsperf.com/uncurrythis
+
+var array_slice = uncurryThis(Array.prototype.slice);
+
+var array_reduce = uncurryThis(
+    Array.prototype.reduce || function (callback, basis) {
+        var index = 0,
+            length = this.length;
+        // concerning the initial value, if one is not provided
+        if (arguments.length === 1) {
+            // seek to the first value in the array, accounting
+            // for the possibility that is is a sparse array
+            do {
+                if (index in this) {
+                    basis = this[index++];
+                    break;
+                }
+                if (++index >= length) {
+                    throw new TypeError();
+                }
+            } while (1);
+        }
+        // reduce
+        for (; index < length; index++) {
+            // account for the possibility that the array is sparse
+            if (index in this) {
+                basis = callback(basis, this[index], index);
+            }
+        }
+        return basis;
+    }
+);
+
+var array_indexOf = uncurryThis(
+    Array.prototype.indexOf || function (value) {
+        // not a very good shim, but good enough for our one use of it
+        for (var i = 0; i < this.length; i++) {
+            if (this[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+);
+
+var array_map = uncurryThis(
+    Array.prototype.map || function (callback, thisp) {
+        var self = this;
+        var collect = [];
+        array_reduce(self, function (undefined, value, index) {
+            collect.push(callback.call(thisp, value, index, self));
+        }, void 0);
+        return collect;
+    }
+);
+
+var object_create = Object.create || function (prototype) {
+    function Type() { }
+    Type.prototype = prototype;
+    return new Type();
+};
+
+var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
+
+var object_keys = Object.keys || function (object) {
+    var keys = [];
+    for (var key in object) {
+        if (object_hasOwnProperty(object, key)) {
+            keys.push(key);
+        }
+    }
+    return keys;
+};
+
+var object_toString = uncurryThis(Object.prototype.toString);
+
+function isObject(value) {
+    return value === Object(value);
+}
+
+// generator related shims
+
+// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
+function isStopIteration(exception) {
+    return (
+        object_toString(exception) === "[object StopIteration]" ||
+        exception instanceof QReturnValue
+    );
+}
+
+// FIXME: Remove this helper and Q.return once ES6 generators are in
+// SpiderMonkey.
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+    QReturnValue = ReturnValue;
+} else {
+    QReturnValue = function (value) {
+        this.value = value;
+    };
+}
+
+// long stack traces
+
+var STACK_JUMP_SEPARATOR = "From previous event:";
+
+function makeStackTraceLong(error, promise) {
+    // If possible, transform the error stack trace by removing Node and Q
+    // cruft, then concatenating with the stack trace of `promise`. See #57.
+    if (hasStacks &&
+        promise.stack &&
+        typeof error === "object" &&
+        error !== null &&
+        error.stack &&
+        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
+    ) {
+        var stacks = [];
+        for (var p = promise; !!p; p = p.source) {
+            if (p.stack) {
+                stacks.unshift(p.stack);
+            }
+        }
+        stacks.unshift(error.stack);
+
+        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
+        error.stack = filterStackString(concatedStacks);
+    }
+}
+
+function filterStackString(stackString) {
+    var lines = stackString.split("\n");
+    var desiredLines = [];
+    for (var i = 0; i < lines.length; ++i) {
+        var line = lines[i];
+
+        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
+            desiredLines.push(line);
+        }
+    }
+    return desiredLines.join("\n");
+}
+
+function isNodeFrame(stackLine) {
+    return stackLine.indexOf("(module.js:") !== -1 ||
+           stackLine.indexOf("(node.js:") !== -1;
+}
+
+function getFileNameAndLineNumber(stackLine) {
+    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
+    // In IE10 function name can have spaces ("Anonymous function") O_o
+    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
+    if (attempt1) {
+        return [attempt1[1], Number(attempt1[2])];
+    }
+
+    // Anonymous functions: "at filename:lineNumber:columnNumber"
+    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
+    if (attempt2) {
+        return [attempt2[1], Number(attempt2[2])];
+    }
+
+    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
+    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
+    if (attempt3) {
+        return [attempt3[1], Number(attempt3[2])];
+    }
+}
+
+function isInternalFrame(stackLine) {
+    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
+
+    if (!fileNameAndLineNumber) {
+        return false;
+    }
+
+    var fileName = fileNameAndLineNumber[0];
+    var lineNumber = fileNameAndLineNumber[1];
+
+    return fileName === qFileName &&
+        lineNumber >= qStartingLine &&
+        lineNumber <= qEndingLine;
+}
+
+// discover own file name and line number range for filtering stack
+// traces
+function captureLine() {
+    if (!hasStacks) {
+        return;
+    }
+
+    try {
+        throw new Error();
+    } catch (e) {
+        var lines = e.stack.split("\n");
+        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
+        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
+        if (!fileNameAndLineNumber) {
+            return;
+        }
+
+        qFileName = fileNameAndLineNumber[0];
+        return fileNameAndLineNumber[1];
+    }
+}
+
+function deprecate(callback, name, alternative) {
+    return function () {
+        if (typeof console !== "undefined" &&
+            typeof console.warn === "function") {
+            console.warn(name + " is deprecated, use " + alternative +
+                         " instead.", new Error("").stack);
+        }
+        return callback.apply(callback, arguments);
+    };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Constructs a promise for an immediate reference, passes promises through, or
+ * coerces promises from different systems.
+ * @param value immediate reference or promise
+ */
+function Q(value) {
+    // If the object is already a Promise, return it directly.  This enables
+    // the resolve function to both be used to created references from objects,
+    // but to tolerably coerce non-promises to promises.
+    if (value instanceof Promise) {
+        return value;
+    }
+
+    // assimilate thenables
+    if (isPromiseAlike(value)) {
+        return coerce(value);
+    } else {
+        return fulfill(value);
+    }
+}
+Q.resolve = Q;
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+Q.nextTick = nextTick;
+
+/**
+ * Controls whether or not long stack traces will be on
+ */
+Q.longStackSupport = false;
+
+/**
+ * Constructs a {promise, resolve, reject} object.
+ *
+ * `resolve` is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
+ * thenable, or invoke `reject` with the reason directly. To resolve the
+ * promise to another thenable, thus putting it in the same state, invoke
+ * `resolve` with that other thenable.
+ */
+Q.defer = defer;
+function defer() {
+    // if "messages" is an "Array", that indicates that the promise has not yet
+    // been resolved.  If it is "undefined", it has been resolved.  Each
+    // element of the messages array is itself an array of complete arguments to
+    // forward to the resolved promise.  We coerce the resolution value to a
+    // promise using the `resolve` function because it handles both fully
+    // non-thenable values and other thenables gracefully.
+    var messages = [], progressListeners = [], resolvedPromise;
+
+    var deferred = object_create(defer.prototype);
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, operands) {
+        var args = array_slice(arguments);
+        if (messages) {
+            messages.push(args);
+            if (op === "when" && operands[1]) { // progress operand
+                progressListeners.push(operands[1]);
+            }
+        } else {
+            nextTick(function () {
+                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
+            });
+        }
+    };
+
+    // XXX deprecated
+    promise.valueOf = function () {
+        if (messages) {
+            return promise;
+        }
+        var nearerValue = nearer(resolvedPromise);
+        if (isPromise(nearerValue)) {
+            resolvedPromise = nearerValue; // shorten chain
+        }
+        return nearerValue;
+    };
+
+    promise.inspect = function () {
+        if (!resolvedPromise) {
+            return { state: "pending" };
+        }
+        return resolvedPromise.inspect();
+    };
+
+    if (Q.longStackSupport && hasStacks) {
+        try {
+            throw new Error();
+        } catch (e) {
+            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
+            // accessor around; that causes memory leaks as per GH-111. Just
+            // reify the stack trace as a string ASAP.
+            //
+            // At the same time, cut off the first line; it's always just
+            // "[object Promise]\n", as per the `toString`.
+            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
+        }
+    }
+
+    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
+    // consolidating them into `become`, since otherwise we'd create new
+    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
+
+    function become(newPromise) {
+        resolvedPromise = newPromise;
+        promise.source = newPromise;
+
+        array_reduce(messages, function (undefined, message) {
+            nextTick(function () {
+                newPromise.promiseDispatch.apply(newPromise, message);
+            });
+        }, void 0);
+
+        messages = void 0;
+        progressListeners = void 0;
+    }
+
+    deferred.promise = promise;
+    deferred.resolve = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(Q(value));
+    };
+
+    deferred.fulfill = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(fulfill(value));
+    };
+    deferred.reject = function (reason) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(reject(reason));
+    };
+    deferred.notify = function (progress) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        array_reduce(progressListeners, function (undefined, progressListener) {
+            nextTick(function () {
+                progressListener(progress);
+            });
+        }, void 0);
+    };
+
+    return deferred;
+}
+
+/**
+ * Creates a Node-style callback that will resolve or reject the deferred
+ * promise.
+ * @returns a nodeback
+ */
+defer.prototype.makeNodeResolver = function () {
+    var self = this;
+    return function (error, value) {
+        if (error) {
+            self.reject(error);
+        } else if (arguments.length > 2) {
+            self.resolve(array_slice(arguments, 1));
+        } else {
+            self.resolve(value);
+        }
+    };
+};
+
+/**
+ * @param resolver {Function} a function that returns nothing and accepts
+ * the resolve, reject, and notify functions for a deferred.
+ * @returns a promise that may be resolved with the given resolve and reject
+ * functions, or rejected by a thrown exception in resolver
+ */
+Q.Promise = promise; // ES6
+Q.promise = promise;
+function promise(resolver) {
+    if (typeof resolver !== "function") {
+        throw new TypeError("resolver must be a function.");
+    }
+    var deferred = defer();
+    try {
+        resolver(deferred.resolve, deferred.reject, deferred.notify);
+    } catch (reason) {
+        deferred.reject(reason);
+    }
+    return deferred.promise;
+}
+
+promise.race = race; // ES6
+promise.all = all; // ES6
+promise.reject = reject; // ES6
+promise.resolve = Q; // ES6
+
+// XXX experimental.  This method is a way to denote that a local value is
+// serializable and should be immediately dispatched to a remote upon request,
+// instead of passing a reference.
+Q.passByCopy = function (object) {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return object;
+};
+
+Promise.prototype.passByCopy = function () {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return this;
+};
+
+/**
+ * If two promises eventually fulfill to the same value, promises that value,
+ * but otherwise rejects.
+ * @param x {Any*}
+ * @param y {Any*}
+ * @returns {Any*} a promise for x and y if they are the same, but a rejection
+ * otherwise.
+ *
+ */
+Q.join = function (x, y) {
+    return Q(x).join(y);
+};
+
+Promise.prototype.join = function (that) {
+    return Q([this, that]).spread(function (x, y) {
+        if (x === y) {
+            // TODO: "===" should be Object.is or equiv
+            return x;
+        } else {
+            throw new Error("Can't join: not the same: " + x + " " + y);
+        }
+    });
+};
+
+/**
+ * Returns a promise for the first of an array of promises to become fulfilled.
+ * @param answers {Array[Any*]} promises to race
+ * @returns {Any*} the first promise to be fulfilled
+ */
+Q.race = race;
+function race(answerPs) {
+    return promise(function(resolve, reject) {
+        // Switch to this once we can assume at least ES5
+        // answerPs.forEach(function(answerP) {
+        //     Q(answerP).then(resolve, reject);
+        // });
+        // Use this in the meantime
+        for (var i = 0, len = answerPs.length; i < len; i++) {
+            Q(answerPs[i]).then(resolve, reject);
+        }
+    });
+}
+
+Promise.prototype.race = function () {
+    return this.then(Q.race);
+};
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function.  The descriptor contains methods like when(rejected), get(name),
+ * set(name, value), post(name, args), and delete(name), which all
+ * return either a value, a promise for a value, or a rejection.  The fallback
+ * accepts the operation name, a resolver, and any further arguments that would
+ * have been forwarded to the appropriate method above had a method been
+ * provided with the proper name.  The API makes no guarantees about the nature
+ * of the returned object, apart from that it is usable whereever promises are
+ * bought and sold.
+ */
+Q.makePromise = Promise;
+function Promise(descriptor, fallback, inspect) {
+    if (fallback === void 0) {
+        fallback = function (op) {
+            return reject(new Error(
+                "Promise does not support operation: " + op
+            ));
+        };
+    }
+    if (inspect === void 0) {
+        inspect = function () {
+            return {state: "unknown"};
+        };
+    }
+
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, args) {
+        var result;
+        try {
+            if (descriptor[op]) {
+                result = descriptor[op].apply(promise, args);
+            } else {
+                result = fallback.call(promise, op, args);
+            }
+        } catch (exception) {
+            result = reject(exception);
+        }
+        if (resolve) {
+            resolve(result);
+        }
+    };
+
+    promise.inspect = inspect;
+
+    // XXX deprecated `valueOf` and `exception` support
+    if (inspect) {
+        var inspected = inspect();
+        if (inspected.state === "rejected") {
+            promise.exception = inspected.reason;
+        }
+
+        promise.valueOf = function () {
+            var inspected = inspect();
+            if (inspected.state === "pending" ||
+                inspected.state === "rejected") {
+                return promise;
+            }
+            return inspected.value;
+        };
+    }
+
+    return promise;
+}
+
+Promise.prototype.toString = function () {
+    return "[object Promise]";
+};
+
+Promise.prototype.then = function (fulfilled, rejected, progressed) {
+    var self = this;
+    var deferred = defer();
+    var done = false;   // ensure the untrusted promise makes at most a
+                        // single call to one of the callbacks
+
+    function _fulfilled(value) {
+        try {
+            return typeof fulfilled === "function" ? fulfilled(value) : value;
+        } catch (exception) {
+            return reject(exception);
+        }
+    }
+
+    function _rejected(exception) {
+        if (typeof rejected === "function") {
+            makeStackTraceLong(exception, self);
+            try {
+                return rejected(exception);
+            } catch (newException) {
+                return reject(newException);
+            }
+        }
+        return reject(exception);
+    }
+
+    function _progressed(value) {
+        return typeof progressed === "function" ? progressed(value) : value;
+    }
+
+    nextTick(function () {
+        self.promiseDispatch(function (value) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_fulfilled(value));
+        }, "when", [function (exception) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_rejected(exception));
+        }]);
+    });
+
+    // Progress propagator need to be attached in the current tick.
+    self.promiseDispatch(void 0, "when", [void 0, function (value) {
+        var newValue;
+        var threw = false;
+        try {
+            newValue = _progressed(value);
+        } catch (e) {
+            threw = true;
+            if (Q.onerror) {
+                Q.onerror(e);
+            } else {
+                throw e;
+            }
+        }
+
+        if (!threw) {
+            deferred.notify(newValue);
+        }
+    }]);
+
+    return deferred.promise;
+};
+
+/**
+ * Registers an observer on a promise.
+ *
+ * Guarantees:
+ *
+ * 1. that fulfilled and rejected will be called only once.
+ * 2. that either the fulfilled callback or the rejected callback will be
+ *    called, but not both.
+ * 3. that fulfilled and rejected will not be called in this turn.
+ *
+ * @param value      promise or immediate reference to observe
+ * @param fulfilled  function to be called with the fulfilled value
+ * @param rejected   function to be called with the rejection exception
+ * @param progressed function to be called on any progress notifications
+ * @return promise for the return value from the invoked callback
+ */
+Q.when = when;
+function when(value, fulfilled, rejected, progressed) {
+    return Q(value).then(fulfilled, rejected, progressed);
+}
+
+Promise.prototype.thenResolve = function (value) {
+    return this.then(function () { return value; });
+};
+
+Q.thenResolve = function (promise, value) {
+    return Q(promise).thenResolve(value);
+};
+
+Promise.prototype.thenReject = function (reason) {
+    return this.then(function () { throw reason; });
+};
+
+Q.thenReject = function (promise, reason) {
+    return Q(promise).thenReject(reason);
+};
+
+/**
+ * If an object is not a promise, it is as "near" as possible.
+ * If a promise is rejected, it is as "near" as possible too.
+ * If it’s a fulfilled promise, the fulfillment value is nearer.
+ * If it’s a deferred promise and the deferred has been resolved, the
+ * resolution is "nearer".
+ * @param object
+ * @returns most resolved (nearest) form of the object
+ */
+
+// XXX should we re-do this?
+Q.nearer = nearer;
+function nearer(value) {
+    if (isPromise(value)) {
+        var inspected = value.inspect();
+        if (inspected.state === "fulfilled") {
+            return inspected.value;
+        }
+    }
+    return value;
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+Q.isPromise = isPromise;
+function isPromise(object) {
+    return isObject(object) &&
+        typeof object.promiseDispatch === "function" &&
+        typeof object.inspect === "function";
+}
+
+Q.isPromiseAlike = isPromiseAlike;
+function isPromiseAlike(object) {
+    return isObject(object) && typeof object.then === "function";
+}
+
+/**
+ * @returns whether the given object is a pending promise, meaning not
+ * fulfilled or rejected.
+ */
+Q.isPending = isPending;
+function isPending(object) {
+    return isPromise(object) && object.inspect().state === "pending";
+}
+
+Promise.prototype.isPending = function () {
+    return this.inspect().state === "pending";
+};
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+Q.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+    return !isPromise(object) || object.inspect().state === "fulfilled";
+}
+
+Promise.prototype.isFulfilled = function () {
+    return this.inspect().state === "fulfilled";
+};
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+Q.isRejected = isRejected;
+function isRejected(object) {
+    return isPromise(object) && object.inspect().state === "rejected";
+}
+
+Promise.prototype.isRejected = function () {
+    return this.inspect().state === "rejected";
+};
+
+//// BEGIN UNHANDLED REJECTION TRACKING
+
+// This promise library consumes exceptions thrown in handlers so they can be
+// handled by a subsequent promise.  The exceptions get added to this array when
+// they are created, and removed when they are handled.  Note that in ES6 or
+// shimmed environments, this would naturally be a `Set`.
+var unhandledReasons = [];
+var unhandledRejections = [];
+var trackUnhandledRejections = true;
+
+function resetUnhandledRejections() {
+    unhandledReasons.length = 0;
+    unhandledRejections.length = 0;
+
+    if (!trackUnhandledRejections) {
+        trackUnhandledRejections = true;
+    }
+}
+
+function trackRejection(promise, reason) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    unhandledRejections.push(promise);
+    if (reason && typeof reason.stack !== "undefined") {
+        unhandledReasons.push(reason.stack);
+    } else {
+        unhandledReasons.push("(no stack) " + reason);
+    }
+}
+
+function untrackRejection(promise) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    var at = array_indexOf(unhandledRejections, promise);
+    if (at !== -1) {
+        unhandledRejections.splice(at, 1);
+        unhandledReasons.splice(at, 1);
+    }
+}
+
+Q.resetUnhandledRejections = resetUnhandledRejections;
+
+Q.getUnhandledReasons = function () {
+    // Make a copy so that consumers can't interfere with our internal state.
+    return unhandledReasons.slice();
+};
+
+Q.stopUnhandledRejectionTracking = function () {
+    resetUnhandledRejections();
+    trackUnhandledRejections = false;
+};
+
+resetUnhandledRejections();
+
+//// END UNHANDLED REJECTION TRACKING
+
+/**
+ * Constructs a rejected promise.
+ * @param reason value describing the failure
+ */
+Q.reject = reject;
+function reject(reason) {
+    var rejection = Promise({
+        "when": function (rejected) {
+            // note that the error has been handled
+            if (rejected) {
+                untrackRejection(this);
+            }
+            return rejected ? rejected(reason) : this;
+        }
+    }, function fallback() {
+        return this;
+    }, function inspect() {
+        return { state: "rejected", reason: reason };
+    });
+
+    // Note that the reason has not been handled.
+    trackRejection(rejection, reason);
+
+    return rejection;
+}
+
+/**
+ * Constructs a fulfilled promise for an immediate reference.
+ * @param value immediate reference
+ */
+Q.fulfill = fulfill;
+function fulfill(value) {
+    return Promise({
+        "when": function () {
+            return value;
+        },
+        "get": function (name) {
+            return value[name];
+        },
+        "set": function (name, rhs) {
+            value[name] = rhs;
+        },
+        "delete": function (name) {
+            delete value[name];
+        },
+        "post": function (name, args) {
+            // Mark Miller proposes that post with no name should apply a
+            // promised function.
+            if (name === null || name === void 0) {
+                return value.apply(void 0, args);
+            } else {
+                return value[name].apply(value, args);
+            }
+        },
+        "apply": function (thisp, args) {
+            return value.apply(thisp, args);
+        },
+        "keys": function () {
+            return object_keys(value);
+        }
+    }, void 0, function inspect() {
+        return { state: "fulfilled", value: value };
+    });
+}
+
+/**
+ * Converts thenables to Q promises.
+ * @param promise thenable promise
+ * @returns a Q promise
+ */
+function coerce(promise) {
+    var deferred = defer();
+    nextTick(function () {
+        try {
+            promise.then(deferred.resolve, deferred.reject, deferred.notify);
+        } catch (exception) {
+            deferred.reject(exception);
+        }
+    });
+    return deferred.promise;
+}
+
+/**
+ * Annotates an object such that it will never be
+ * transferred away from this process over any promise
+ * communication channel.
+ * @param object
+ * @returns promise a wrapping of that object that
+ * additionally responds to the "isDef" message
+ * without a rejection.
+ */
+Q.master = master;
+function master(object) {
+    return Promise({
+        "isDef": function () {}
+    }, function fallback(op, args) {
+        return dispatch(object, op, args);
+    }, function () {
+        return Q(object).inspect();
+    });
+}
+
+/**
+ * Spreads the values of a promised array of arguments into the
+ * fulfillment callback.
+ * @param fulfilled callback that receives variadic arguments from the
+ * promised array
+ * @param rejected callback that receives the exception if the promise
+ * is rejected.
+ * @returns a promise for the return value or thrown exception of
+ * either callback.
+ */
+Q.spread = spread;
+function spread(value, fulfilled, rejected) {
+    return Q(value).spread(fulfilled, rejected);
+}
+
+Promise.prototype.spread = function (fulfilled, rejected) {
+    return this.all().then(function (array) {
+        return fulfilled.apply(void 0, array);
+    }, rejected);
+};
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators.  Although generators are only part
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
+ * errors in older engines.  This code should continue to work and will
+ * in fact improve over time as the language improves.
+ *
+ * ES6 generators are currently part of V8 version 3.19 with the
+ * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
+ * for longer, but under an older Python-inspired form.  This function
+ * works on both kinds of generators.
+ *
+ * Decorates a generator function such that:
+ *  - it may yield promises
+ *  - execution will continue when that promise is fulfilled
+ *  - the value of the yield expression will be the fulfilled value
+ *  - it returns a promise for the return value (when the generator
+ *    stops iterating)
+ *  - the decorated function returns a promise for the return value
+ *    of the generator or the first rejected promise among those
+ *    yielded.
+ *  - if an error is thrown in the generator, it propagates through
+ *    every following yield until it is caught, or until it escapes
+ *    the generator function altogether, and is translated into a
+ *    rejection for the promise returned by the decorated generator.
+ */
+Q.async = async;
+function async(makeGenerator) {
+    return function () {
+        // when verb is "send", arg is a value
+        // when verb is "throw", arg is an exception
+        function continuer(verb, arg) {
+            var result;
+
+            // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
+            // engine that has a deployed base of browsers that support generators.
+            // However, SM's generators use the Python-inspired semantics of
+            // outdated ES6 drafts.  We would like to support ES6, but we'd also
+            // like to make it possible to use generators in deployed browsers, so
+            // we also support Python-style generators.  At some point we can remove
+            // this block.
+
+            if (typeof StopIteration === "undefined") {
+                // ES6 Generators
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    return reject(exception);
+                }
+                if (result.done) {
+                    return Q(result.value);
+                } else {
+                    return when(result.value, callback, errback);
+                }
+            } else {
+                // SpiderMonkey Generators
+                // FIXME: Remove this case when SM does ES6 generators.
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    if (isStopIteration(exception)) {
+                        return Q(exception.value);
+                    } else {
+                        return reject(exception);
+                    }
+                }
+                return when(result, callback, errback);
+            }
+        }
+        var generator = makeGenerator.apply(this, arguments);
+        var callback = continuer.bind(continuer, "next");
+        var errback = continuer.bind(continuer, "throw");
+        return callback();
+    };
+}
+
+/**
+ * The spawn function is a small wrapper around async that immediately
+ * calls the generator and also ends the promise chain, so that any
+ * unhandled errors are thrown instead of forwarded to the error
+ * handler. This is useful because it's extremely common to run
+ * generators at the top-level to work with libraries.
+ */
+Q.spawn = spawn;
+function spawn(makeGenerator) {
+    Q.done(Q.async(makeGenerator)());
+}
+
+// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ *
+ * This interface is a stop-gap measure to support generator return
+ * values in older Firefox/SpiderMonkey.  In browsers that support ES6
+ * generators like Chromium 29, just use "return" in your generator
+ * functions.
+ *
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * // ES6 style
+ * Q.async(function* () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      return foo + bar;
+ * })
+ * // Older SpiderMonkey style
+ * Q.async(function () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      Q.return(foo + bar);
+ * })
+ */
+Q["return"] = _return;
+function _return(value) {
+    throw new QReturnValue(value);
+}
+
+/**
+ * The promised function decorator ensures that any promise arguments
+ * are settled and passed as values (`this` is also settled and passed
+ * as a value).  It will also ensure that the result of a function is
+ * always a promise.
+ *
+ * @example
+ * var add = Q.promised(function (a, b) {
+ *     return a + b;
+ * });
+ * add(Q(a), Q(B));
+ *
+ * @param {function} callback The function to decorate
+ * @returns {function} a function that has been decorated.
+ */
+Q.promised = promised;
+function promised(callback) {
+    return function () {
+        return spread([this, all(arguments)], function (self, args) {
+            return callback.apply(self, args);
+        });
+    };
+}
+
+/**
+ * sends a message to a value in a future turn
+ * @param object* the recipient
+ * @param op the name of the message operation, e.g., "when",
+ * @param args further arguments to be forwarded to the operation
+ * @returns result {Promise} a promise for the result of the operation
+ */
+Q.dispatch = dispatch;
+function dispatch(object, op, args) {
+    return Q(object).dispatch(op, args);
+}
+
+Promise.prototype.dispatch = function (op, args) {
+    var self = this;
+    var deferred = defer();
+    nextTick(function () {
+        self.promiseDispatch(deferred.resolve, op, args);
+    });
+    return deferred.promise;
+};
+
+/**
+ * Gets the value of a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to get
+ * @return promise for the property value
+ */
+Q.get = function (object, key) {
+    return Q(object).dispatch("get", [key]);
+};
+
+Promise.prototype.get = function (key) {
+    return this.dispatch("get", [key]);
+};
+
+/**
+ * Sets the value of a property in a future turn.
+ * @param object    promise or immediate reference for object object
+ * @param name      name of property to set
+ * @param value     new value of property
+ * @return promise for the return value
+ */
+Q.set = function (object, key, value) {
+    return Q(object).dispatch("set", [key, value]);
+};
+
+Promise.prototype.set = function (key, value) {
+    return this.dispatch("set", [key, value]);
+};
+
+/**
+ * Deletes a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to delete
+ * @return promise for the return value
+ */
+Q.del = // XXX legacy
+Q["delete"] = function (object, key) {
+    return Q(object).dispatch("delete", [key]);
+};
+
+Promise.prototype.del = // XXX legacy
+Promise.prototype["delete"] = function (key) {
+    return this.dispatch("delete", [key]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param value     a value to post, typically an array of
+ *                  invocation arguments for promises that
+ *                  are ultimately backed with `resolve` values,
+ *                  as opposed to those backed with URLs
+ *                  wherein the posted value can be any
+ *                  JSON serializable object.
+ * @return promise for the return value
+ */
+// bound locally because it is used by other methods
+Q.mapply = // XXX As proposed by "Redsandro"
+Q.post = function (object, name, args) {
+    return Q(object).dispatch("post", [name, args]);
+};
+
+Promise.prototype.mapply = // XXX As proposed by "Redsandro"
+Promise.prototype.post = function (name, args) {
+    return this.dispatch("post", [name, args]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param ...args   array of invocation arguments
+ * @return promise for the return value
+ */
+Q.send = // XXX Mark Miller's proposed parlance
+Q.mcall = // XXX As proposed by "Redsandro"
+Q.invoke = function (object, name /*...args*/) {
+    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
+};
+
+Promise.prototype.send = // XXX Mark Miller's proposed parlance
+Promise.prototype.mcall = // XXX As proposed by "Redsandro"
+Promise.prototype.invoke = function (name /*...args*/) {
+    return this.dispatch("post", [name, array_slice(arguments, 1)]);
+};
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param args      array of application arguments
+ */
+Q.fapply = function (object, args) {
+    return Q(object).dispatch("apply", [void 0, args]);
+};
+
+Promise.prototype.fapply = function (args) {
+    return this.dispatch("apply", [void 0, args]);
+};
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q["try"] =
+Q.fcall = function (object /* ...args*/) {
+    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
+};
+
+Promise.prototype.fcall = function (/*...args*/) {
+    return this.dispatch("apply", [void 0, array_slice(arguments)]);
+};
+
+/**
+ * Binds the promised function, transforming return values into a fulfilled
+ * promise and thrown errors into a rejected one.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q.fbind = function (object /*...args*/) {
+    var promise = Q(object);
+    var args = array_slice(arguments, 1);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+Promise.prototype.fbind = function (/*...args*/) {
+    var promise = this;
+    var args = array_slice(arguments);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+
+/**
+ * Requests the names of the owned properties of a promised
+ * object in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @return promise for the keys of the eventually settled object
+ */
+Q.keys = function (object) {
+    return Q(object).dispatch("keys", []);
+};
+
+Promise.prototype.keys = function () {
+    return this.dispatch("keys", []);
+};
+
+/**
+ * Turns an array of promises into a promise for an array.  If any of
+ * the promises gets rejected, the whole array is rejected immediately.
+ * @param {Array*} an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns a promise for an array of the corresponding values
+ */
+// By Mark Miller
+// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
+Q.all = all;
+function all(promises) {
+    return when(promises, function (promises) {
+        var countDown = 0;
+        var deferred = defer();
+        array_reduce(promises, function (undefined, promise, index) {
+            var snapshot;
+            if (
+                isPromise(promise) &&
+                (snapshot = promise.inspect()).state === "fulfilled"
+            ) {
+                promises[index] = snapshot.value;
+            } else {
+                ++countDown;
+                when(
+                    promise,
+                    function (value) {
+                        promises[index] = value;
+                        if (--countDown === 0) {
+                            deferred.resolve(promises);
+                        }
+                    },
+                    deferred.reject,
+                    function (progress) {
+                        deferred.notify({ index: index, value: progress });
+                    }
+                );
+            }
+        }, void 0);
+        if (countDown === 0) {
+            deferred.resolve(promises);
+        }
+        return deferred.promise;
+    });
+}
+
+Promise.prototype.all = function () {
+    return all(this);
+};
+
+/**
+ * Waits for all promises to be settled, either fulfilled or
+ * rejected.  This is distinct from `all` since that would stop
+ * waiting at the first rejection.  The promise returned by
+ * `allResolved` will never be rejected.
+ * @param promises a promise for an array (or an array) of promises
+ * (or values)
+ * @return a promise for an array of promises
+ */
+Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
+function allResolved(promises) {
+    return when(promises, function (promises) {
+        promises = array_map(promises, Q);
+        return when(all(array_map(promises, function (promise) {
+            return when(promise, noop, noop);
+        })), function () {
+            return promises;
+        });
+    });
+}
+
+Promise.prototype.allResolved = function () {
+    return allResolved(this);
+};
+
+/**
+ * @see Promise#allSettled
+ */
+Q.allSettled = allSettled;
+function allSettled(promises) {
+    return Q(promises).allSettled();
+}
+
+/**
+ * Turns an array of promises into a promise for an array of their states (as
+ * returned by `inspect`) when they have all settled.
+ * @param {Array[Any*]} values an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns {Array[State]} an array of states for the respective values.
+ */
+Promise.prototype.allSettled = function () {
+    return this.then(function (promises) {
+        return all(array_map(promises, function (promise) {
+            promise = Q(promise);
+            function regardless() {
+                return promise.inspect();
+            }
+            return promise.then(regardless, regardless);
+        }));
+    });
+};
+
+/**
+ * Captures the failure of a promise, giving an oportunity to recover
+ * with a callback.  If the given promise is fulfilled, the returned
+ * promise is fulfilled.
+ * @param {Any*} promise for something
+ * @param {Function} callback to fulfill the returned promise if the
+ * given promise is rejected
+ * @returns a promise for the return value of the callback
+ */
+Q.fail = // XXX legacy
+Q["catch"] = function (object, rejected) {
+    return Q(object).then(void 0, rejected);
+};
+
+Promise.prototype.fail = // XXX legacy
+Promise.prototype["catch"] = function (rejected) {
+    return this.then(void 0, rejected);
+};
+
+/**
+ * Attaches a listener that can respond to progress notifications from a
+ * promise's originating deferred. This listener receives the exact arguments
+ * passed to ``deferred.notify``.
+ * @param {Any*} promise for something
+ * @param {Function} callback to receive any progress notifications
+ * @returns the given promise, unchanged
+ */
+Q.progress = progress;
+function progress(object, progressed) {
+    return Q(object).then(void 0, void 0, progressed);
+}
+
+Promise.prototype.progress = function (progressed) {
+    return this.then(void 0, void 0, progressed);
+};
+
+/**
+ * Provides an opportunity to observe the settling of a promise,
+ * regardless of whether the promise is fulfilled or rejected.  Forwards
+ * the resolution to the returned promise when the callback is done.
+ * The callback can return a promise to defer completion.
+ * @param {Any*} promise
+ * @param {Function} callback to observe the resolution of the given
+ * promise, takes no arguments.
+ * @returns a promise for the resolution of the given promise when
+ * ``fin`` is done.
+ */
+Q.fin = // XXX legacy
+Q["finally"] = function (object, callback) {
+    return Q(object)["finally"](callback);
+};
+
+Promise.prototype.fin = // XXX legacy
+Promise.prototype["finally"] = function (callback) {
+    callback = Q(callback);
+    return this.then(function (value) {
+        return callback.fcall().then(function () {
+            return value;
+        });
+    }, function (reason) {
+        // TODO attempt to recycle the rejection with "this".
+        return callback.fcall().then(function () {
+            throw reason;
+        });
+    });
+};
+
+/**
+ * Terminates a chain of promises, forcing rejections to be
+ * thrown as exceptions.
+ * @param {Any*} promise at the end of a chain of promises
+ * @returns nothing
+ */
+Q.done = function (object, fulfilled, rejected, progress) {
+    return Q(object).done(fulfilled, rejected, progress);
+};
+
+Promise.prototype.done = function (fulfilled, rejected, progress) {
+    var onUnhandledError = function (error) {
+        // forward to a future turn so that ``when``
+        // does not catch it and turn it into a rejection.
+        nextTick(function () {
+            makeStackTraceLong(error, promise);
+            if (Q.onerror) {
+                Q.onerror(error);
+            } else {
+                throw error;
+            }
+        });
+    };
+
+    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
+    var promise = fulfilled || rejected || progress ?
+        this.then(fulfilled, rejected, progress) :
+        this;
+
+    if (typeof process === "object" && process && process.domain) {
+        onUnhandledError = process.domain.bind(onUnhandledError);
+    }
+
+    promise.then(void 0, onUnhandledError);
+};
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @param {Any*} custom error message or Error object (optional)
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+Q.timeout = function (object, ms, error) {
+    return Q(object).timeout(ms, error);
+};
+
+Promise.prototype.timeout = function (ms, error) {
+    var deferred = defer();
+    var timeoutId = setTimeout(function () {
+        if (!error || "string" === typeof error) {
+            error = new Error(error || "Timed out after " + ms + " ms");
+            error.code = "ETIMEDOUT";
+        }
+        deferred.reject(error);
+    }, ms);
+
+    this.then(function (value) {
+        clearTimeout(timeoutId);
+        deferred.resolve(value);
+    }, function (exception) {
+        clearTimeout(timeoutId);
+        deferred.reject(exception);
+    }, deferred.notify);
+
+    return deferred.promise;
+};
+
+/**
+ * Returns a promise for the given value (or promised value), some
+ * milliseconds after it resolved. Passes rejections immediately.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after milliseconds
+ * time has elapsed since the resolution of the given promise.
+ * If the given promise rejects, that is passed immediately.
+ */
+Q.delay = function (object, timeout) {
+    if (timeout === void 0) {
+        timeout = object;
+        object = void 0;
+    }
+    return Q(object).delay(timeout);
+};
+
+Promise.prototype.delay = function (timeout) {
+    return this.then(function (value) {
+        var deferred = defer();
+        setTimeout(function () {
+            deferred.resolve(value);
+        }, timeout);
+        return deferred.promise;
+    });
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided as an array, and returns a promise.
+ *
+ *      Q.nfapply(FS.readFile, [__filename])
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfapply = function (callback, args) {
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfapply = function (args) {
+    var deferred = defer();
+    var nodeArgs = array_slice(args);
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided individually, and returns a promise.
+ * @example
+ * Q.nfcall(FS.readFile, __filename)
+ * .then(function (content) {
+ * })
+ *
+ */
+Q.nfcall = function (callback /*...args*/) {
+    var args = array_slice(arguments, 1);
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfcall = function (/*...args*/) {
+    var nodeArgs = array_slice(arguments);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ * @example
+ * Q.nfbind(FS.readFile, __filename)("utf-8")
+ * .then(console.log)
+ * .done()
+ */
+Q.nfbind =
+Q.denodeify = function (callback /*...args*/) {
+    var baseArgs = array_slice(arguments, 1);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        Q(callback).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nfbind =
+Promise.prototype.denodeify = function (/*...args*/) {
+    var args = array_slice(arguments);
+    args.unshift(this);
+    return Q.denodeify.apply(void 0, args);
+};
+
+Q.nbind = function (callback, thisp /*...args*/) {
+    var baseArgs = array_slice(arguments, 2);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        function bound() {
+            return callback.apply(thisp, arguments);
+        }
+        Q(bound).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nbind = function (/*thisp, ...args*/) {
+    var args = array_slice(arguments, 0);
+    args.unshift(this);
+    return Q.nbind.apply(void 0, args);
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback with a given array of arguments, plus a provided callback.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param {Array} args arguments to pass to the method; the callback
+ * will be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nmapply = // XXX As proposed by "Redsandro"
+Q.npost = function (object, name, args) {
+    return Q(object).npost(name, args);
+};
+
+Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
+Promise.prototype.npost = function (name, args) {
+    var nodeArgs = array_slice(args || []);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback, forwarding the given variadic arguments, plus a provided
+ * callback argument.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param ...args arguments to pass to the method; the callback will
+ * be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nsend = // XXX Based on Mark Miller's proposed "send"
+Q.nmcall = // XXX Based on "Redsandro's" proposal
+Q.ninvoke = function (object, name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 2);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
+Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
+Promise.prototype.ninvoke = function (name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 1);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * If a function would like to support both Node continuation-passing-style and
+ * promise-returning-style, it can end its internal promise chain with
+ * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
+ * elects to use a nodeback, the result will be sent there.  If they do not
+ * pass a nodeback, they will receive the result promise.
+ * @param object a result (or a promise for a result)
+ * @param {Function} nodeback a Node.js-style callback
+ * @returns either the promise or nothing
+ */
+Q.nodeify = nodeify;
+function nodeify(object, nodeback) {
+    return Q(object).nodeify(nodeback);
+}
+
+Promise.prototype.nodeify = function (nodeback) {
+    if (nodeback) {
+        this.then(function (value) {
+            nextTick(function () {
+                nodeback(null, value);
+            });
+        }, function (error) {
+            nextTick(function () {
+                nodeback(error);
+            });
+        });
+    } else {
+        return this;
+    }
+};
+
+// All code before this point will be filtered from stack traces.
+var qEndingLine = captureLine();
+
+return Q;
+
+});
+
diff --git a/mist/assets/ext/qml_messaging.js b/mist/assets/ext/qml_messaging.js
new file mode 100644
index 0000000000000000000000000000000000000000..8222c848d7632629e0247e9a9dcc99ec319f770a
--- /dev/null
+++ b/mist/assets/ext/qml_messaging.js
@@ -0,0 +1,13 @@
+function HandleMessage(data) {
+	var message;
+	try { message = JSON.parse(data) } catch(e) {};
+
+	if(message) {
+		switch(message.type) {
+			case "coinbase":
+				return eth.coinBase();
+			case "block":
+				return eth.blockByNumber(0);
+		}
+	}
+}
diff --git a/ethereal/assets/ext/string.js b/mist/assets/ext/string.js
similarity index 100%
rename from ethereal/assets/ext/string.js
rename to mist/assets/ext/string.js
diff --git a/ethereal/assets/ext/test.html b/mist/assets/ext/test.html
similarity index 100%
rename from ethereal/assets/ext/test.html
rename to mist/assets/ext/test.html
diff --git a/ethereal/assets/facet.png b/mist/assets/facet.png
similarity index 100%
rename from ethereal/assets/facet.png
rename to mist/assets/facet.png
diff --git a/ethereal/assets/heart.png b/mist/assets/heart.png
similarity index 100%
rename from ethereal/assets/heart.png
rename to mist/assets/heart.png
diff --git a/mist/assets/icecream.png b/mist/assets/icecream.png
new file mode 100644
index 0000000000000000000000000000000000000000..2438ca845b9fcf9228fd36333b305ed3da85f5ae
Binary files /dev/null and b/mist/assets/icecream.png differ
diff --git a/ethereal/assets/muted/codemirror.css b/mist/assets/muted/codemirror.css
similarity index 100%
rename from ethereal/assets/muted/codemirror.css
rename to mist/assets/muted/codemirror.css
diff --git a/ethereal/assets/muted/debugger.html b/mist/assets/muted/debugger.html
similarity index 100%
rename from ethereal/assets/muted/debugger.html
rename to mist/assets/muted/debugger.html
diff --git a/ethereal/assets/muted/eclipse.css b/mist/assets/muted/eclipse.css
similarity index 100%
rename from ethereal/assets/muted/eclipse.css
rename to mist/assets/muted/eclipse.css
diff --git a/ethereal/assets/muted/index.html b/mist/assets/muted/index.html
similarity index 100%
rename from ethereal/assets/muted/index.html
rename to mist/assets/muted/index.html
diff --git a/ethereal/assets/muted/lib/codemirror.js b/mist/assets/muted/lib/codemirror.js
similarity index 100%
rename from ethereal/assets/muted/lib/codemirror.js
rename to mist/assets/muted/lib/codemirror.js
diff --git a/ethereal/assets/muted/lib/go.js b/mist/assets/muted/lib/go.js
similarity index 100%
rename from ethereal/assets/muted/lib/go.js
rename to mist/assets/muted/lib/go.js
diff --git a/ethereal/assets/muted/lib/matchbrackets.js b/mist/assets/muted/lib/matchbrackets.js
similarity index 100%
rename from ethereal/assets/muted/lib/matchbrackets.js
rename to mist/assets/muted/lib/matchbrackets.js
diff --git a/ethereal/assets/muted/muted.js b/mist/assets/muted/muted.js
similarity index 100%
rename from ethereal/assets/muted/muted.js
rename to mist/assets/muted/muted.js
diff --git a/ethereal/assets/net.png b/mist/assets/net.png
similarity index 100%
rename from ethereal/assets/net.png
rename to mist/assets/net.png
diff --git a/ethereal/assets/network.png b/mist/assets/network.png
similarity index 100%
rename from ethereal/assets/network.png
rename to mist/assets/network.png
diff --git a/ethereal/assets/new.png b/mist/assets/new.png
similarity index 100%
rename from ethereal/assets/new.png
rename to mist/assets/new.png
diff --git a/ethereal/assets/pick.png b/mist/assets/pick.png
similarity index 100%
rename from ethereal/assets/pick.png
rename to mist/assets/pick.png
diff --git a/ethereal/assets/qml/QmlApp.qml b/mist/assets/qml/QmlApp.qml
similarity index 100%
rename from ethereal/assets/qml/QmlApp.qml
rename to mist/assets/qml/QmlApp.qml
diff --git a/ethereal/assets/qml/first_run.qml b/mist/assets/qml/first_run.qml
similarity index 100%
rename from ethereal/assets/qml/first_run.qml
rename to mist/assets/qml/first_run.qml
diff --git a/ethereal/assets/qml/muted.qml b/mist/assets/qml/muted.qml
similarity index 100%
rename from ethereal/assets/qml/muted.qml
rename to mist/assets/qml/muted.qml
diff --git a/ethereal/assets/qml/test_app.qml b/mist/assets/qml/test_app.qml
similarity index 100%
rename from ethereal/assets/qml/test_app.qml
rename to mist/assets/qml/test_app.qml
diff --git a/ethereal/assets/qml/transactions.qml b/mist/assets/qml/transactions.qml
similarity index 100%
rename from ethereal/assets/qml/transactions.qml
rename to mist/assets/qml/transactions.qml
diff --git a/ethereal/assets/qml/views/chain.qml b/mist/assets/qml/views/chain.qml
similarity index 86%
rename from ethereal/assets/qml/views/chain.qml
rename to mist/assets/qml/views/chain.qml
index 9eaa49db18016a35f81e93c4d91445bddd0aca4c..130ff8bb978febd8a268a142d6be512b888021ce 100644
--- a/ethereal/assets/qml/views/chain.qml
+++ b/mist/assets/qml/views/chain.qml
@@ -10,7 +10,6 @@ Rectangle {
 	id: root
 	property var title: "Network"
 	property var iconSource: "../net.png"
-	property var secondary: "Hi"
 	property var menuItem
 
 	objectName: "chainView"
@@ -99,20 +98,23 @@ Rectangle {
 
 
 	function addBlock(block, initial) {
-		var txs = JSON.parse(block.transactions);
-		var amount = 0
 		if(initial == undefined){
 			initial = false
 		}
 
+		/*
+		var txs = JSON.parse(block.transactions);
 		if(txs != null){
 			amount = txs.length
 		}
+		*/
+	       var txs = block.transactions;
+	       var amount = block.transactions.length;
 
 		if(initial){
-			blockModel.append({number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
+			blockModel.append({size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
 		} else {
-			blockModel.insert(0, {number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
+			blockModel.insert(0, {size: block.size, number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
 		}
 
 		//root.secondary.text = "#" + block.number;
@@ -137,7 +139,7 @@ Rectangle {
 					anchors.top: parent.top
 					anchors.left: parent.left
 					Text { text: '<h3>Block details</h3>'; color: "#F2F2F2"}
-					Text { text: '<b>Block number:</b> ' + number; color: "#F2F2F2"}
+					Text { text: '<b>Block number:</b> ' + number + " (Size: " + size + ")"; color: "#F2F2F2"}
 					Text { text: '<b>Hash:</b> ' + hash; color: "#F2F2F2"}
 					Text { text: '<b>Coinbase:</b> &lt;' + name + '&gt; ' + coinbase; color: "#F2F2F2"}
 					Text { text: '<b>Block found at:</b> ' + prettyTime; color: "#F2F2F2"}
@@ -242,11 +244,11 @@ Rectangle {
 			singleBlock.set(0,block)
 			popup.height = 300
 			transactionModel.clear()
-			if(block.txs != undefined){
-				for(var i = 0; i < block.txs.count; ++i) {
+			if(block.txs !== undefined){
+				for(var i = 0; i < block.txs.length; i++) {
 					transactionModel.insert(0, block.txs.get(i))
 				}
-				if(block.txs.get(0).data){
+				if(block.txs.length > 0 && block.txs.get(0).data){
 					popup.showContractData(block.txs.get(0))
 				}
 			}
diff --git a/ethereal/assets/qml/views/history.qml b/mist/assets/qml/views/history.qml
similarity index 100%
rename from ethereal/assets/qml/views/history.qml
rename to mist/assets/qml/views/history.qml
diff --git a/ethereal/assets/qml/views/info.qml b/mist/assets/qml/views/info.qml
similarity index 55%
rename from ethereal/assets/qml/views/info.qml
rename to mist/assets/qml/views/info.qml
index ca6ca077e0d310838a11775d42e0d58ce44d1c3f..8a1d4d84ae477ec743f901bd18ca7590dcb9376e 100644
--- a/ethereal/assets/qml/views/info.qml
+++ b/mist/assets/qml/views/info.qml
@@ -44,59 +44,103 @@ Rectangle {
 				gui.setCustomIdentifier(text)
 			}
 		}
-	}
 
-	property var addressModel: ListModel {
-		id: addressModel
+		TextArea {
+			objectName: "statsPane"
+			width: parent.width
+			height: 200
+			selectByMouse: true
+			readOnly: true
+			font.family: "Courier"
+		}
 	}
-	TableView {
-		id: addressView
+
+	RowLayout {
+		id: logLayout
 		width: parent.width
 		height: 200
-		anchors.bottom: logLayout.top
-		TableViewColumn{ role: "name"; title: "name" }
-		TableViewColumn{ role: "address"; title: "address"; width: 300}
-
-		model: addressModel
-		itemDelegate: Item {
-			Text {
-				anchors {
-					left: parent.left
-					right: parent.right
-					leftMargin: 10
-					verticalCenter: parent.verticalCenter
-				}
-				color: styleData.textColor
-				elide: styleData.elideMode
-				text: styleData.value
-				font.pixelSize: 11
-				MouseArea {
-					acceptedButtons: Qt.LeftButton | Qt.RightButton
-					propagateComposedEvents: true
-					anchors.fill: parent
-					onClicked: {
-						addressView.selection.clear()
-						addressView.selection.select(styleData.row)
-
-						if(mouse.button == Qt.RightButton) {
-							contextMenu.row = styleData.row;
-							contextMenu.popup()
+		anchors.bottom: parent.bottom
+
+		TableView {
+			id: addressView
+			width: parent.width
+			height: 200
+			anchors {
+				left: parent.left
+				right: logLevelSlider.left
+				bottom: parent.bottom
+				top: parent.top
+			}
+			TableViewColumn{ role: "name"; title: "name" }
+			TableViewColumn{ role: "address"; title: "address"; width: 300}
+
+			property var addressModel: ListModel {
+				id: addressModel
+			}
+
+			model: addressModel
+			itemDelegate: Item {
+				Text {
+					anchors {
+						left: parent.left
+						right: parent.right
+						leftMargin: 10
+						verticalCenter: parent.verticalCenter
+					}
+					color: styleData.textColor
+					elide: styleData.elideMode
+					text: styleData.value
+					font.pixelSize: 11
+					MouseArea {
+						acceptedButtons: Qt.LeftButton | Qt.RightButton
+						propagateComposedEvents: true
+						anchors.fill: parent
+						onClicked: {
+							addressView.selection.clear()
+							addressView.selection.select(styleData.row)
+
+							if(mouse.button == Qt.RightButton) {
+								contextMenu.row = styleData.row;
+								contextMenu.popup()
+							}
 						}
 					}
 				}
 			}
 
+			Menu {
+				id: contextMenu
+				property var row;
+
+				MenuItem {
+					text: "Copy"
+					onTriggered: {
+						copyToClipboard(addressModel.get(this.row).address)
+					}
+				}
+			}
 		}
 
-		Menu {
-			id: contextMenu
-			property var row;
+		Slider {
+			id: logLevelSlider
+			value: gui.getLogLevelInt()
+			anchors {
+				right: parent.right
+				top: parent.top
+				bottom: parent.bottom
 
-			MenuItem {
-				text: "Copy"
-				onTriggered: {
-					copyToClipboard(addressModel.get(this.row).address)
-				}
+				rightMargin: 5
+				leftMargin: 5
+				topMargin: 5
+				bottomMargin: 5
+			}
+
+			orientation: Qt.Vertical
+			maximumValue: 5
+			stepSize: 1
+
+			onValueChanged: {
+				gui.setLogLevel(value)
 			}
 		}
 	}
@@ -104,6 +148,8 @@ Rectangle {
 	property var logModel: ListModel {
 		id: logModel
 	}
+
+	/*
 	RowLayout {
 		id: logLayout
 		width: parent.width
@@ -147,6 +193,7 @@ Rectangle {
 			}
 		}
 	}
+	*/
 
 	function addDebugMessage(message){
 		debuggerLog.append({value: message})
diff --git a/ethereal/assets/qml/views/javascript.qml b/mist/assets/qml/views/javascript.qml
similarity index 100%
rename from ethereal/assets/qml/views/javascript.qml
rename to mist/assets/qml/views/javascript.qml
diff --git a/mist/assets/qml/views/jeffcoin/jeff.png b/mist/assets/qml/views/jeffcoin/jeff.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b9c6651a922ddf3fa209455b0a9bf4317d6c133
Binary files /dev/null and b/mist/assets/qml/views/jeffcoin/jeff.png differ
diff --git a/mist/assets/qml/views/jeffcoin/jeffcoin.qml b/mist/assets/qml/views/jeffcoin/jeffcoin.qml
new file mode 100644
index 0000000000000000000000000000000000000000..6a57791a7f1d4907b488ba24841918ed48d1328a
--- /dev/null
+++ b/mist/assets/qml/views/jeffcoin/jeffcoin.qml
@@ -0,0 +1,184 @@
+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
+
+Rectangle {
+	id: root
+	property var title: "JeffCoin"
+	property var iconSource: "./views/jeffcoin/jeff.png"
+	property var menuItem
+	property var filter
+	property var address: "fc0a9436890478bb9b1c6ed7455c2535366f4a99"
+
+	function insertTx(message, blockNumber) {
+		if(!message) return;
+
+		var from = message.from
+		var to = message.input.substr(24, 40)
+		var value = eth.fromNumber(message.input.substr(64, 64))
+
+		var me = eth.key().address;
+		if((to == me|| from == me) && message.input.length == 128) {
+			txModel.insert(0, {confirmations: blockNumber - message.number, from: from, to: to, value: value})
+		}
+	}
+
+	function setBalance() {
+		var jeffCoinAmount = eth.fromNumber(eth.storageAt(address, eth.key().address)) + " JΞF"
+		menuItem.secondaryTitle = jeffCoinAmount
+
+		balance.text = "<b>Balance</b>: " + jeffCoinAmount;
+	}
+
+	function onReady() {
+		setBalance()
+
+		filter = new ethx.watch({latest: -1, to: address})
+		filter.changed(function(messages) {
+			setBalance()
+
+			var blockNumber = eth.block(-1).number;
+			for(var i = 0; i < messages.length; i++) {
+				insertTx(messages.get(i), blockNumber);
+			}
+		});
+
+		var blockNumber = eth.block(-1).number;
+		var messages = filter.messages()
+		for(var i = messages.length-1; i >= 0; i--) {
+			var message = messages.get(i)
+
+			insertTx(message, blockNumber)
+		}
+
+		var chainChanged = ethx.watch("chain")
+		chainChanged.changed(function() {
+			for(var i = 0; i < txModel.count; i++) {
+				var entry = txModel.get(i);
+				entry.confirmations++;
+			}
+		});
+	}
+
+	function onDestroy() {
+		filter.uninstall()
+	}
+
+	ColumnLayout {
+		spacing: 10
+		y: 40
+		anchors.fill: parent
+
+		Text {
+			id: balance
+			text: "<b>Balance</b>: " + eth.fromNumber(eth.storageAt(address, eth.key().address)) + " JΞF"
+			font.pixelSize: 24
+			anchors {
+				horizontalCenter: parent.horizontalCenter
+				top: parent.top
+				topMargin: 20
+			}
+		}
+
+		Rectangle {
+			id: newTxPane
+			color: "#ececec"
+			border.color: "#cccccc"
+			border.width: 1
+			anchors {
+				top: balance.bottom
+				topMargin: 10
+				left: parent.left
+				leftMargin: 5
+				right: parent.right
+				rightMargin: 5
+			}
+			height: 100
+
+			RowLayout {
+				id: amountFields
+				spacing: 10
+				anchors {
+					top: parent.top
+					topMargin: 20
+					left: parent.left
+					leftMargin: 20
+				}
+
+				Text {
+					text: "JΞF  "
+				}
+
+				// There's something off with the row layout where textfields won't listen to the width setting
+				Rectangle {
+					width: 50
+					height: 20
+					TextField {
+						id: txValue
+						width: parent.width
+						placeholderText: "0.00"
+					}
+				}
+			}
+
+			RowLayout {
+				id: toFields
+				spacing: 10
+				anchors {
+					top: amountFields.bottom
+					topMargin: 5
+					left: parent.left
+					leftMargin: 20
+				}
+
+				Text {
+					text: "To"
+				}
+
+				Rectangle {
+					width: 200
+					height: 20
+					TextField {
+						id: txTo
+						width: parent.width
+						placeholderText: "Address or name"
+					}
+				}
+
+				Button {
+					text: "Send"
+					onClicked: {
+						eth.transact({from: eth.key().privateKey, to:address, gas: "9000", gasPrice: "100000000000", data: ["0x"+txTo.text, txValue.text]})
+					}
+				}
+			}
+		}
+
+		Rectangle {
+			anchors {
+				left: parent.left
+				right: parent.right
+				top: newTxPane.bottom
+				topMargin: 10
+				bottom: parent.bottom
+			}
+			TableView {
+				id: txTableView
+				anchors.fill : parent
+				TableViewColumn{ role: "value" ; title: "Amount" ; width: 100 }
+				TableViewColumn{ role: "from" ; title: "From" ; width: 280 }
+				TableViewColumn{ role: "to" ; title: "To" ; width: 280 }
+				TableViewColumn{ role: "confirmations" ; title: "Confirmations" ; width: 100 }
+
+				model: ListModel {
+					id: txModel
+					Component.onCompleted: {
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/ethereal/assets/qml/views/pending_tx.qml b/mist/assets/qml/views/pending_tx.qml
similarity index 100%
rename from ethereal/assets/qml/views/pending_tx.qml
rename to mist/assets/qml/views/pending_tx.qml
diff --git a/ethereal/assets/qml/views/transaction.qml b/mist/assets/qml/views/transaction.qml
similarity index 99%
rename from ethereal/assets/qml/views/transaction.qml
rename to mist/assets/qml/views/transaction.qml
index fb8ba8a6d75efd2d7558625bdf31d21fc38ec2e5..7d689733fa321d61352708bf66e83c337f713556 100644
--- a/ethereal/assets/qml/views/transaction.qml
+++ b/mist/assets/qml/views/transaction.qml
@@ -180,6 +180,8 @@ Rectangle {
 					txResult.text = "Your transaction has been submitted:\n"
 					txOutput.text = res[0].address
 					mainContractColumn.state = "DONE"
+
+					console.log(res)
 				}
 			}
 		}
diff --git a/ethereal/assets/qml/views/wallet.qml b/mist/assets/qml/views/wallet.qml
similarity index 89%
rename from ethereal/assets/qml/views/wallet.qml
rename to mist/assets/qml/views/wallet.qml
index 5e10a70224f78e43dc218e1b64ce19ebdd770233..fbe1dfd0e494bc2799fbfaa914e20ad7a2cefc02 100644
--- a/ethereal/assets/qml/views/wallet.qml
+++ b/mist/assets/qml/views/wallet.qml
@@ -9,7 +9,7 @@ import Ethereum 1.0
 Rectangle {
 	id: root
 	property var title: "Wallet"
-	property var iconSource: "../wallet.png"
+	property var iconSource: "../facet.png"
 	property var menuItem
 
 	objectName: "walletView"
@@ -151,10 +151,16 @@ Rectangle {
 				model: ListModel {
 					id: txModel
 					Component.onCompleted: {
-						var messages = JSON.parse(eth.messages({latest: -1, from: "e6716f9544a56c530d868e4bfbacb172315bdead"}))
+                        var filter = ethx.watch({latest: -1, from: eth.key().address});
+						filter.changed(addTxs)
+
+						addTxs(filter.messages())
+					}
+
+					function addTxs(messages) {
 						for(var i = 0; i < messages.length; i++) {
-							var message = messages[i];
-							this.insert(0, {num: i, from: message.from, to: message.to, value: eth.numberToHuman(message.value)})
+							var message = messages.get(i);
+							txModel.insert(0, {num: txModel.count, from: message.from, to: message.to, value: eth.numberToHuman(message.value)})
 						}
 					}
 				}
diff --git a/mist/assets/qml/wallet.qml b/mist/assets/qml/wallet.qml
new file mode 100644
index 0000000000000000000000000000000000000000..24191eae8d4889a727696fb09ca9f9dfc3c602ea
--- /dev/null
+++ b/mist/assets/qml/wallet.qml
@@ -0,0 +1,894 @@
+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
+import "../ext/http.js" as Http
+
+ApplicationWindow {
+    id: root
+
+    property alias miningButtonText: miningButton.text
+    property var ethx : Eth.ethx
+    property var web
+
+    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.web.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.web = browser.view;
+
+        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
+        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: 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.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: {
+                          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})
+        }
+
+        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
+                 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
new file mode 100644
index 0000000000000000000000000000000000000000..8801b6b47f4b76fe7db2f56ba7aa708c664c41e6
--- /dev/null
+++ b/mist/assets/qml/webapp.qml
@@ -0,0 +1,409 @@
+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
+
+import "../ext/qml_messaging.js" as Messaging
+
+//ApplicationWindow {
+	Rectangle {
+		id: window
+		property var title: "Browser"
+		property var iconSource: "../browser.png"
+		property var menuItem
+
+		property alias url: webview.url
+		property alias webView: webview
+
+		Component.onCompleted: {
+			webview.url = "http://etherian.io"
+		}
+
+		signal messages(var messages, int id);
+		onMessages: {
+			// Bit of a cheat to get proper JSON
+			var m = JSON.parse(JSON.parse(JSON.stringify(messages)))
+			webview.postEvent("messages", [m, id]);
+		}
+
+		Item {
+			objectName: "root"
+			id: root
+			anchors.fill: parent
+			state: "inspectorShown"
+
+			RowLayout {
+				id: navBar
+				height: 40
+				anchors {
+					left: parent.left
+					right: parent.right
+					leftMargin: 7
+				}
+
+				Button {
+					id: back
+					onClicked: {
+						webview.goBack()
+					}
+					style: ButtonStyle {
+						background: Image {
+							source: "../back.png"
+							width: 30
+							height: 30
+						}
+					}
+				}
+
+				TextField {
+					anchors {
+						left: back.right
+						right: toggleInspector.left
+						leftMargin: 5
+						rightMargin: 5
+					}
+					text: "http://etherian.io"
+					id: uriNav
+					y: parent.height / 2 - this.height / 2
+
+					Keys.onReturnPressed: {
+						webview.url = this.text;
+					}
+				}
+
+				Button {
+					id: toggleInspector
+					anchors {
+						right: parent.right
+					}
+					iconSource: "../bug.png"
+					onClicked: {
+						if(inspector.visible == true){
+							inspector.visible = false
+						}else{
+							inspector.visible = true
+							inspector.url = webview.experimental.remoteInspectorUrl
+						}
+					}
+				}
+			}
+
+
+			WebView {
+				objectName: "webView"
+				id: webview
+				anchors {
+					left: parent.left
+					right: parent.right
+					bottom: parent.bottom
+					top: navBar.bottom
+				}
+
+				property var cleanPath: false
+				onNavigationRequested: {
+					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 = eth.lookupDomain(domain.substring(0, domain.length - 4));
+								var ip = [];
+								for(var i = 0, l = lookup.length; i < l; i++) {
+									ip.push(lookup.charCodeAt(i))
+								}
+
+								if(ip.length != 0) {
+									uri += lookup;
+								} else {
+									uri += domain;
+								}
+
+								uri += path;
+							});
+						}
+
+						this.cleanPath = true;
+
+						webview.url = uri;
+					} else {
+						// Prevent inf loop.
+						this.cleanPath = false;
+					}
+				}
+
+				function sendMessage(data) {
+					webview.experimental.postMessage(JSON.stringify(data))
+				}
+
+				onTitleChanged: {
+					var data = Messaging.HandleMessage(title);
+					if(data) {
+						sendMessage(data)
+					}
+				}
+
+				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.onMessageReceived: {
+					console.log("[onMessageReceived]: ", message.data)
+					// TODO move to messaging.js
+					var data = JSON.parse(message.data)
+
+					try {
+						switch(data.call) {
+							case "compile":
+							postData(data._seed, eth.compile(data.args[0]))
+							break
+
+							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 "getCountAt":
+							require(1)
+							postData(data._seed, eth.txCountAt(data.args[0]))
+
+							break
+
+							case "getCodeAt":
+							require(1)
+							var code = eth.codeAt(data.args[0])
+							postData(data._seed, code);
+
+							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)
+							postData(data._seed, tx)
+
+							break
+
+							case "getStorageAt":
+							require(2);
+
+							var storage = eth.storageAt(data.args[0], data.args[1]);
+							postData(data._seed, storage)
+
+							break
+
+							case "call":
+							require(1);
+							var ret = eth.call(data.args)
+							postData(data._seed, ret)
+
+							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 "getBalanceAt":
+							require(1);
+
+							postData(data._seed, eth.balanceAt(data.args[0]));
+
+							break
+
+							case "getKey":
+							var key = eth.key().privateKey;
+
+							postData(data._seed, key)
+							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)
+
+							var addr = eth.secretToAddress(data.args[0])
+							console.log("getsecret", addr)
+							postData(data._seed, addr)
+
+							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;
+
+							case "newFilterString":
+							require(1)
+							var id = eth.newFilterString(data.args[0])
+							postData(data._seed, id);
+							break;
+							case "newFilter":
+							require(1)
+							var id = eth.newFilter(data.args[0])
+
+							postData(data._seed, id);
+							break;
+
+							case "getMessages":
+							require(1);
+
+							var messages = eth.messages(data.args[0]);
+							var m = JSON.parse(JSON.parse(JSON.stringify(messages)))
+							postData(data._seed, m);
+
+							break;
+
+							case "deleteFilter":
+							require(1);
+							eth.uninstallFilter(data.args[0])
+							break;
+						}
+					} catch(e) {
+						console.log(data.call + ": " + e)
+
+						postData(data._seed, null);
+					}
+				}
+
+
+				function post(seed, 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/ethereal/assets/tx.png b/mist/assets/tx.png
similarity index 100%
rename from ethereal/assets/tx.png
rename to mist/assets/tx.png
diff --git a/ethereal/assets/util/test.html b/mist/assets/util/test.html
similarity index 100%
rename from ethereal/assets/util/test.html
rename to mist/assets/util/test.html
diff --git a/ethereal/assets/wallet.png b/mist/assets/wallet.png
similarity index 100%
rename from ethereal/assets/wallet.png
rename to mist/assets/wallet.png
diff --git a/mist/bindings.go b/mist/bindings.go
new file mode 100644
index 0000000000000000000000000000000000000000..141c4a469fb7340f5057bc17e22158545fe0db4e
--- /dev/null
+++ b/mist/bindings.go
@@ -0,0 +1,148 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+	"strconv"
+
+	"github.com/ethereum/eth-go/ethchain"
+	"github.com/ethereum/eth-go/ethlog"
+	"github.com/ethereum/eth-go/ethpipe"
+	"github.com/ethereum/eth-go/ethutil"
+	"github.com/ethereum/go-ethereum/utils"
+)
+
+type plugin struct {
+	Name string `json:"name"`
+	Path string `json:"path"`
+}
+
+func (gui *Gui) Println(v ...interface{}) {
+	gui.printLog(fmt.Sprintln(v...))
+}
+
+func (gui *Gui) Printf(format string, v ...interface{}) {
+	gui.printLog(fmt.Sprintf(format, v...))
+}
+
+// Print function that logs directly to the GUI
+func (gui *Gui) printLog(s string) {
+	/*
+		str := strings.TrimRight(s, "\n")
+		lines := strings.Split(str, "\n")
+
+		view := gui.getObjectByName("infoView")
+		for _, line := range lines {
+			view.Call("addLog", line)
+		}
+	*/
+}
+func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (*ethpipe.JSReceipt, error) {
+	var data string
+	if len(recipient) == 0 {
+		code, err := ethutil.Compile(d, false)
+		if err != nil {
+			return nil, err
+		}
+		data = ethutil.Bytes2Hex(code)
+	} else {
+		data = ethutil.Bytes2Hex(utils.FormatTransactionData(d))
+	}
+
+	return gui.pipe.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data)
+}
+
+func (gui *Gui) SetCustomIdentifier(customIdentifier string) {
+	gui.clientIdentity.SetCustomIdentifier(customIdentifier)
+	gui.config.Save("id", customIdentifier)
+}
+
+func (gui *Gui) GetCustomIdentifier() string {
+	return gui.clientIdentity.GetCustomIdentifier()
+}
+
+func (gui *Gui) ToggleTurboMining() {
+	gui.miner.ToggleTurbo()
+}
+
+// functions that allow Gui to implement interface ethlog.LogSystem
+func (gui *Gui) SetLogLevel(level ethlog.LogLevel) {
+	gui.logLevel = level
+	gui.stdLog.SetLogLevel(level)
+	gui.config.Save("loglevel", level)
+}
+
+func (gui *Gui) GetLogLevel() ethlog.LogLevel {
+	return gui.logLevel
+}
+
+func (self *Gui) AddPlugin(pluginPath string) {
+	self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath}
+
+	json, _ := json.MarshalIndent(self.plugins, "", "    ")
+	ethutil.WriteFile(ethutil.Config.ExecPath+"/plugins.json", json)
+}
+
+func (self *Gui) RemovePlugin(pluginPath string) {
+	delete(self.plugins, pluginPath)
+
+	json, _ := json.MarshalIndent(self.plugins, "", "    ")
+	ethutil.WriteFile(ethutil.Config.ExecPath+"/plugins.json", json)
+}
+
+// this extra function needed to give int typecast value to gui widget
+// that sets initial loglevel to default
+func (gui *Gui) GetLogLevelInt() int {
+	return int(gui.logLevel)
+}
+func (self *Gui) DumpState(hash, path string) {
+	var stateDump []byte
+
+	if len(hash) == 0 {
+		stateDump = self.eth.StateManager().CurrentState().Dump()
+	} else {
+		var block *ethchain.Block
+		if hash[0] == '#' {
+			i, _ := strconv.Atoi(hash[1:])
+			block = self.eth.BlockChain().GetBlockByNumber(uint64(i))
+		} else {
+			block = self.eth.BlockChain().GetBlock(ethutil.Hex2Bytes(hash))
+		}
+
+		if block == nil {
+			logger.Infof("block err: not found %s\n", hash)
+			return
+		}
+
+		stateDump = block.State().Dump()
+	}
+
+	file, err := os.OpenFile(path[7:], os.O_CREATE|os.O_RDWR, os.ModePerm)
+	if err != nil {
+		logger.Infoln("dump err: ", err)
+		return
+	}
+	defer file.Close()
+
+	logger.Infof("dumped state (%s) to %s\n", hash, path)
+
+	file.Write(stateDump)
+}
+func (gui *Gui) ToggleMining() {
+	var txt string
+	if gui.eth.Mining {
+		utils.StopMining(gui.eth)
+		txt = "Start mining"
+
+		gui.getObjectByName("miningLabel").Set("visible", false)
+	} else {
+		utils.StartMining(gui.eth)
+		gui.miner = utils.GetMiner()
+		txt = "Stop mining"
+
+		gui.getObjectByName("miningLabel").Set("visible", true)
+	}
+
+	gui.win.Root().Set("miningButtonText", txt)
+}
diff --git a/ethereal/debugger.go b/mist/debugger.go
similarity index 90%
rename from ethereal/debugger.go
rename to mist/debugger.go
index 7bc544377d70c3dd42123216449ad66926e2da67..9d1de8c4251803670e4938d9d99c1a43889f3fe7 100644
--- a/ethereal/debugger.go
+++ b/mist/debugger.go
@@ -5,6 +5,7 @@ import (
 	"math/big"
 	"strconv"
 	"strings"
+	"unicode"
 
 	"github.com/ethereum/eth-go/ethchain"
 	"github.com/ethereum/eth-go/ethstate"
@@ -93,9 +94,7 @@ func (self *DebuggerWindow) ClearLog() {
 }
 
 func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) {
-	if !self.Db.done {
-		self.Db.Q <- true
-	}
+	self.Stop()
 
 	defer func() {
 		if r := recover(); r != nil {
@@ -185,6 +184,12 @@ func (self *DebuggerWindow) Continue() {
 	self.Next()
 }
 
+func (self *DebuggerWindow) Stop() {
+	if !self.Db.done {
+		self.Db.Q <- true
+	}
+}
+
 func (self *DebuggerWindow) ExecCommand(command string) {
 	if len(command) > 0 {
 		cmd := strings.Split(command, " ")
@@ -271,9 +276,20 @@ func (d *Debugger) halting(pc int, op ethvm.OpCode, mem *ethvm.Memory, stack *et
 	d.win.Root().Call("clearStorage")
 
 	addr := 0
-	for i := 0; i+32 <= mem.Len(); i += 32 {
-		d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])})
-		addr++
+	for i := 0; i+16 <= mem.Len(); i += 16 {
+		dat := mem.Data()[i : i+16]
+		var str string
+
+		for _, d := range dat {
+			if unicode.IsGraphic(rune(d)) {
+				str += string(d)
+			} else {
+				str += "?"
+			}
+		}
+
+		d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("%s  % x", str, dat)})
+		addr += 16
 	}
 
 	for _, val := range stack.Data() {
@@ -284,6 +300,12 @@ func (d *Debugger) halting(pc int, op ethvm.OpCode, mem *ethvm.Memory, stack *et
 		d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
 	})
 
+	stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32))
+	psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64())
+	d.win.Root().ObjectByName("stackFrame").Set("text", fmt.Sprintf(`<b>stack ptr</b>: %v`, stackFrameAt))
+	d.win.Root().ObjectByName("stackSize").Set("text", fmt.Sprintf(`<b>stack size</b>: %d`, psize))
+	d.win.Root().ObjectByName("memSize").Set("text", fmt.Sprintf(`<b>mem size</b>: %v`, mem.Len()))
+
 out:
 	for {
 		select {
diff --git a/mist/errors.go b/mist/errors.go
new file mode 100644
index 0000000000000000000000000000000000000000..409b7a281455a740c48391265a3732baa552b968
--- /dev/null
+++ b/mist/errors.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+	"fmt"
+	"os"
+
+	"gopkg.in/qml.v1"
+)
+
+func ErrorWindow(err error) {
+	engine := qml.NewEngine()
+	component, e := engine.LoadString("local", qmlErr)
+	if e != nil {
+		fmt.Println("err:", err)
+		os.Exit(1)
+	}
+
+	win := component.CreateWindow(nil)
+	win.Root().ObjectByName("label").Set("text", err.Error())
+	win.Show()
+	win.Wait()
+}
+
+const qmlErr = `
+import QtQuick 2.0; import QtQuick.Controls 1.0;
+ApplicationWindow {
+	width: 600; height: 150;
+	flags: Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
+	title: "Error"
+	Text {
+		x: parent.width / 2 - this.width / 2;
+		y: parent.height / 2 - this.height / 2;
+		objectName: "label";
+	}
+}
+`
diff --git a/ethereal/ext_app.go b/mist/ext_app.go
similarity index 100%
rename from ethereal/ext_app.go
rename to mist/ext_app.go
diff --git a/ethereal/flags.go b/mist/flags.go
similarity index 94%
rename from ethereal/flags.go
rename to mist/flags.go
index c9327c3d31b49c859e2d22acb59a348141808deb..d2e7d3fb08dc298d70a4db3ee745450470a9ba05 100644
--- a/ethereal/flags.go
+++ b/mist/flags.go
@@ -1,15 +1,16 @@
 package main
 
 import (
-	"bitbucket.org/kardianos/osext"
 	"flag"
 	"fmt"
-	"github.com/ethereum/eth-go/ethlog"
 	"os"
 	"os/user"
 	"path"
 	"path/filepath"
 	"runtime"
+
+	"bitbucket.org/kardianos/osext"
+	"github.com/ethereum/eth-go/ethlog"
 )
 
 var Identifier string
@@ -43,7 +44,7 @@ func defaultAssetPath() string {
 	// assume a debug build and use the source directory as
 	// asset directory.
 	pwd, _ := os.Getwd()
-	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
+	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist") {
 		assetPath = path.Join(pwd, "assets")
 	} else {
 		switch runtime.GOOS {
@@ -52,7 +53,7 @@ func defaultAssetPath() string {
 			exedir, _ := osext.ExecutableFolder()
 			assetPath = filepath.Join(exedir, "../Resources")
 		case "linux":
-			assetPath = "/usr/share/ethereal"
+			assetPath = "/usr/share/mist"
 		case "windows":
 			assetPath = "./assets"
 		default:
@@ -63,7 +64,7 @@ func defaultAssetPath() string {
 }
 func defaultDataDir() string {
 	usr, _ := user.Current()
-	return path.Join(usr.HomeDir, ".ethereal")
+	return path.Join(usr.HomeDir, ".mist")
 }
 
 var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
@@ -78,7 +79,7 @@ func Init() {
 	flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
 	flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
 	flag.StringVar(&OutboundPort, "port", "30303", "listening port")
-	flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
+	flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support")
 	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")
diff --git a/ethereal/gui.go b/mist/gui.go
similarity index 75%
rename from ethereal/gui.go
rename to mist/gui.go
index 6d16ec484d12f9f86dcd421badf6a3d2a66e0a1e..f80e46761581e2bcbd6755f9dc6e2c882c3400d1 100644
--- a/ethereal/gui.go
+++ b/mist/gui.go
@@ -1,11 +1,14 @@
 package main
 
+import "C"
+
 import (
 	"bytes"
 	"encoding/json"
 	"fmt"
 	"math/big"
-	"os"
+	"path"
+	"runtime"
 	"strconv"
 	"strings"
 	"time"
@@ -19,16 +22,33 @@ import (
 	"github.com/ethereum/eth-go/ethreact"
 	"github.com/ethereum/eth-go/ethutil"
 	"github.com/ethereum/eth-go/ethwire"
-	"github.com/ethereum/go-ethereum/utils"
 	"gopkg.in/qml.v1"
 )
 
-var logger = ethlog.NewLogger("GUI")
+/*
+func LoadExtension(path string) (uintptr, error) {
+	lib, err := ffi.NewLibrary(path)
+	if err != nil {
+		return 0, err
+	}
+
+	so, err := lib.Fct("sharedObject", ffi.Pointer, nil)
+	if err != nil {
+		return 0, err
+	}
+
+	ptr := so()
+
+		err = lib.Close()
+		if err != nil {
+			return 0, err
+		}
 
-type plugin struct {
-	Name string `json:"name"`
-	Path string `json:"path"`
+	return ptr.Interface().(uintptr), nil
 }
+*/
+
+var logger = ethlog.NewLogger("GUI")
 
 type Gui struct {
 	// The main application window
@@ -56,7 +76,8 @@ type Gui struct {
 
 	plugins map[string]plugin
 
-	miner *ethminer.Miner
+	miner  *ethminer.Miner
+	stdLog ethlog.LogSystem
 }
 
 // Create GUI, but doesn't start it
@@ -68,12 +89,7 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIden
 
 	pipe := ethpipe.NewJSPipe(ethereum)
 	gui := &Gui{eth: ethereum, txDb: db, pipe: pipe, logLevel: ethlog.LogLevel(logLevel), Session: session, open: false, clientIdentity: clientIdentity, config: config, plugins: make(map[string]plugin)}
-	data, err := ethutil.ReadAllFile(ethutil.Config.ExecPath + "/plugins.json")
-	if err != nil {
-		fmt.Println(err)
-	}
-	fmt.Println("plugins:", string(data))
-
+	data, _ := ethutil.ReadAllFile(path.Join(ethutil.Config.ExecPath, "plugins.json"))
 	json.Unmarshal([]byte(data), &gui.plugins)
 
 	return gui
@@ -100,6 +116,16 @@ func (gui *Gui) Start(assetPath string) {
 	context.SetVar("gui", gui)
 	context.SetVar("eth", gui.uiLib)
 
+	/*
+		vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib")
+		fmt.Printf("Fetched vec with addr: %#x\n", vec)
+		if errr != nil {
+			fmt.Println(errr)
+		} else {
+			context.SetVar("vec", (unsafe.Pointer)(vec))
+		}
+	*/
+
 	// Load the main QML interface
 	data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
 
@@ -145,24 +171,6 @@ func (gui *Gui) Stop() {
 	logger.Infoln("Stopped")
 }
 
-func (gui *Gui) ToggleMining() {
-	var txt string
-	if gui.eth.Mining {
-		utils.StopMining(gui.eth)
-		txt = "Start mining"
-
-		gui.getObjectByName("miningLabel").Set("visible", false)
-	} else {
-		utils.StartMining(gui.eth)
-		gui.miner = utils.GetMiner()
-		txt = "Stop mining"
-
-		gui.getObjectByName("miningLabel").Set("visible", true)
-	}
-
-	gui.win.Root().Set("miningButtonText", txt)
-}
-
 func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
 	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml"))
 	if err != nil {
@@ -176,44 +184,9 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
 	return gui.win, nil
 }
 
-func (self *Gui) DumpState(hash, path string) {
-	var stateDump []byte
-
-	if len(hash) == 0 {
-		stateDump = self.eth.StateManager().CurrentState().Dump()
-	} else {
-		var block *ethchain.Block
-		if hash[0] == '#' {
-			i, _ := strconv.Atoi(hash[1:])
-			block = self.eth.BlockChain().GetBlockByNumber(uint64(i))
-		} else {
-			block = self.eth.BlockChain().GetBlock(ethutil.Hex2Bytes(hash))
-		}
-
-		if block == nil {
-			logger.Infof("block err: not found %s\n", hash)
-			return
-		}
-
-		stateDump = block.State().Dump()
-	}
-
-	file, err := os.OpenFile(path[7:], os.O_CREATE|os.O_RDWR, os.ModePerm)
-	if err != nil {
-		logger.Infoln("dump err: ", err)
-		return
-	}
-	defer file.Close()
-
-	logger.Infof("dumped state (%s) to %s\n", hash, path)
-
-	file.Write(stateDump)
-}
-
 // The done handler will be called by QML when all views have been loaded
 func (gui *Gui) Done() {
 	gui.qmlDone = true
-
 }
 
 func (gui *Gui) ImportKey(filePath string) {
@@ -337,7 +310,7 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
 	ptx.Address = r
 
 	if window == "post" {
-		gui.getObjectByName("transactionView").Call("addTx", ptx, inout)
+		//gui.getObjectByName("transactionView").Call("addTx", ptx, inout)
 	} else {
 		gui.getObjectByName("pendingTxView").Call("addTx", ptx, inout)
 	}
@@ -397,6 +370,8 @@ func (gui *Gui) update() {
 	}()
 
 	for _, plugin := range gui.plugins {
+		logger.Infoln("Loading plugin ", plugin.Name)
+
 		gui.win.Root().Call("addPlugin", plugin.Path, "")
 	}
 
@@ -411,6 +386,7 @@ func (gui *Gui) update() {
 
 	peerUpdateTicker := time.NewTicker(5 * time.Second)
 	generalUpdateTicker := time.NewTicker(1 * time.Second)
+	statsUpdateTicker := time.NewTicker(5 * time.Second)
 
 	state := gui.eth.StateManager().TransState()
 
@@ -450,12 +426,12 @@ func (gui *Gui) update() {
 					if bytes.Compare(tx.Sender(), gui.address()) == 0 {
 						object.SubAmount(tx.Value)
 
-						gui.getObjectByName("transactionView").Call("addTx", ethpipe.NewJSTx(tx), "send")
+						//gui.getObjectByName("transactionView").Call("addTx", ethpipe.NewJSTx(tx), "send")
 						gui.txDb.Put(tx.Hash(), tx.RlpEncode())
 					} else if bytes.Compare(tx.Recipient, gui.address()) == 0 {
 						object.AddAmount(tx.Value)
 
-						gui.getObjectByName("transactionView").Call("addTx", ethpipe.NewJSTx(tx), "recv")
+						//gui.getObjectByName("transactionView").Call("addTx", ethpipe.NewJSTx(tx), "recv")
 						gui.txDb.Put(tx.Hash(), tx.RlpEncode())
 					}
 
@@ -487,6 +463,10 @@ func (gui *Gui) update() {
 					pow := gui.miner.GetPow()
 					miningLabel.Set("text", "Mining @ "+strconv.FormatInt(pow.GetHashrate(), 10)+"Khash")
 				}
+
+			case <-statsUpdateTicker.C:
+				gui.setStatsPane()
+
 			}
 		}
 	}()
@@ -506,9 +486,30 @@ func (gui *Gui) update() {
 	reactor.Subscribe("peerList", peerChan)
 }
 
-func (gui *Gui) CopyToClipboard(data string) {
-	//clipboard.WriteAll("test")
-	fmt.Println("COPY currently BUGGED. Here are the contents:\n", data)
+func (gui *Gui) setStatsPane() {
+	var memStats runtime.MemStats
+	runtime.ReadMemStats(&memStats)
+
+	statsPane := gui.getObjectByName("statsPane")
+	statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.5 (%s) #######
+
+eth %d (p2p = %d)
+
+CPU:        # %d
+Goroutines: # %d
+CGoCalls:   # %d
+
+Alloc:      %d
+Heap Alloc: %d
+
+CGNext:     %x
+NumGC:      %d
+`, runtime.Version(),
+		eth.ProtocolVersion, eth.P2PVersion,
+		runtime.NumCPU, runtime.NumGoroutine(), runtime.NumCgoCall(),
+		memStats.Alloc, memStats.HeapAlloc,
+		memStats.NextGC, memStats.NumGC,
+	))
 }
 
 func (gui *Gui) setPeerInfo() {
@@ -527,82 +528,3 @@ func (gui *Gui) privateKey() string {
 func (gui *Gui) address() []byte {
 	return gui.eth.KeyManager().Address()
 }
-
-func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (*ethpipe.JSReceipt, error) {
-	var data string
-	if len(recipient) == 0 {
-		code, err := ethutil.Compile(d, false)
-		if err != nil {
-			return nil, err
-		}
-		data = ethutil.Bytes2Hex(code)
-	} else {
-		data = ethutil.Bytes2Hex(utils.FormatTransactionData(d))
-	}
-
-	return gui.pipe.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data)
-}
-
-func (gui *Gui) SetCustomIdentifier(customIdentifier string) {
-	gui.clientIdentity.SetCustomIdentifier(customIdentifier)
-	gui.config.Save("id", customIdentifier)
-}
-
-func (gui *Gui) GetCustomIdentifier() string {
-	return gui.clientIdentity.GetCustomIdentifier()
-}
-
-func (gui *Gui) ToggleTurboMining() {
-	gui.miner.ToggleTurbo()
-}
-
-// functions that allow Gui to implement interface ethlog.LogSystem
-func (gui *Gui) SetLogLevel(level ethlog.LogLevel) {
-	gui.logLevel = level
-	gui.config.Save("loglevel", level)
-}
-
-func (gui *Gui) GetLogLevel() ethlog.LogLevel {
-	return gui.logLevel
-}
-
-func (self *Gui) AddPlugin(pluginPath string) {
-	self.plugins[pluginPath] = plugin{Name: "SomeName", Path: pluginPath}
-
-	json, _ := json.MarshalIndent(self.plugins, "", "    ")
-	ethutil.WriteFile(ethutil.Config.ExecPath+"/plugins.json", json)
-}
-
-func (self *Gui) RemovePlugin(pluginPath string) {
-	delete(self.plugins, pluginPath)
-
-	json, _ := json.MarshalIndent(self.plugins, "", "    ")
-	ethutil.WriteFile(ethutil.Config.ExecPath+"/plugins.json", json)
-}
-
-// this extra function needed to give int typecast value to gui widget
-// that sets initial loglevel to default
-func (gui *Gui) GetLogLevelInt() int {
-	return int(gui.logLevel)
-}
-
-func (gui *Gui) Println(v ...interface{}) {
-	gui.printLog(fmt.Sprintln(v...))
-}
-
-func (gui *Gui) Printf(format string, v ...interface{}) {
-	gui.printLog(fmt.Sprintf(format, v...))
-}
-
-// Print function that logs directly to the GUI
-func (gui *Gui) printLog(s string) {
-	/*
-		str := strings.TrimRight(s, "\n")
-		lines := strings.Split(str, "\n")
-
-		view := gui.getObjectByName("infoView")
-		for _, line := range lines {
-			view.Call("addLog", line)
-		}
-	*/
-}
diff --git a/ethereal/html_container.go b/mist/html_container.go
similarity index 100%
rename from ethereal/html_container.go
rename to mist/html_container.go
diff --git a/ethereal/main.go b/mist/main.go
similarity index 88%
rename from ethereal/main.go
rename to mist/main.go
index 4cb8630e80da1e941e3dc35e8163dc1beccab79a..747616f8f31d596b4fb010668afd58e6a6605df0 100644
--- a/ethereal/main.go
+++ b/mist/main.go
@@ -11,8 +11,8 @@ import (
 )
 
 const (
-	ClientIdentifier = "Ethereal"
-	Version          = "0.6.4"
+	ClientIdentifier = "Mist"
+	Version          = "0.6.5"
 )
 
 var ethereum *eth.Ethereum
@@ -25,9 +25,15 @@ func run() error {
 
 	utils.InitDataDir(Datadir)
 
-	utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
+	stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
 
 	db := utils.NewDatabase()
+	err := utils.DBSanityCheck(db)
+	if err != nil {
+		ErrorWindow(err)
+
+		os.Exit(1)
+	}
 
 	keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
 
@@ -47,6 +53,7 @@ func run() error {
 	}
 
 	gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
+	gui.stdLog = stdLog
 
 	utils.RegisterInterrupt(func(os.Signal) {
 		gui.Stop()
@@ -64,7 +71,6 @@ func main() {
 	// This is a bit of a cheat, but ey!
 	os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999")
 
-	//qml.Init(nil)
 	qml.Run(run)
 
 	var interrupted = false
diff --git a/ethereal/qml_container.go b/mist/qml_container.go
similarity index 100%
rename from ethereal/qml_container.go
rename to mist/qml_container.go
diff --git a/ethereal/ui_lib.go b/mist/ui_lib.go
similarity index 69%
rename from ethereal/ui_lib.go
rename to mist/ui_lib.go
index 4b8210da64c41c75570d9c8d694e420917db658a..a913af7db7967964a8079eb137c448fdf684b12a 100644
--- a/ethereal/ui_lib.go
+++ b/mist/ui_lib.go
@@ -37,11 +37,14 @@ type UiLib struct {
 	jsEngine *javascript.JSRE
 
 	filterCallbacks map[int][]int
-	filters         map[int]*GuiFilter
 }
 
 func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
-	return &UiLib{JSPipe: ethpipe.NewJSPipe(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int), filters: make(map[int]*GuiFilter)}
+	return &UiLib{JSPipe: ethpipe.NewJSPipe(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*ethpipe.JSFilter)}
+}
+
+func (self *UiLib) Notef(args []interface{}) {
+	logger.Infoln(args...)
 }
 
 func (self *UiLib) LookupDomain(domain string) string {
@@ -53,7 +56,7 @@ func (self *UiLib) LookupDomain(domain string) string {
 	data := world.Config().Get("DnsReg").StorageString(domain).Bytes()
 
 	// Left padded = A record, Right padded = CNAME
-	if data[0] == 0 {
+	if len(data) > 0 && data[0] == 0 {
 		data = bytes.TrimLeft(data, "\x00")
 		var ipSlice []string
 		for _, d := range data {
@@ -68,6 +71,10 @@ func (self *UiLib) LookupDomain(domain string) string {
 	}
 }
 
+func (self *UiLib) PastPeers() *ethutil.List {
+	return ethutil.NewList(eth.PastPeers())
+}
+
 func (self *UiLib) ImportTx(rlpTx string) {
 	tx := ethchain.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx))
 	self.eth.TxPool().QueueTransaction(tx)
@@ -160,49 +167,40 @@ func (self *UiLib) StartDebugger() {
 	dbWindow.Show()
 }
 
-func (self *UiLib) RegisterFilter(object map[string]interface{}, seed int) {
-	filter := &GuiFilter{ethpipe.NewJSFilterFromMap(object, self.eth), seed}
-	self.filters[seed] = filter
-
+func (self *UiLib) NewFilter(object map[string]interface{}) int {
+	filter, id := self.eth.InstallFilter(object)
 	filter.MessageCallback = func(messages ethstate.Messages) {
-		for _, callbackSeed := range self.filterCallbacks[seed] {
-			self.win.Root().Call("invokeFilterCallback", filter.MessagesToJson(messages), seed, callbackSeed)
-		}
+		self.win.Root().Call("invokeFilterCallback", ethpipe.ToJSMessages(messages), id)
 	}
 
+	return id
 }
 
-func (self *UiLib) RegisterFilterString(typ string, seed int) {
-	filter := &GuiFilter{ethpipe.NewJSFilterFromMap(nil, self.eth), seed}
-	self.filters[seed] = filter
-
-	if typ == "chain" {
-		filter.BlockCallback = func(block *ethchain.Block) {
-			for _, callbackSeed := range self.filterCallbacks[seed] {
-				self.win.Root().Call("invokeFilterCallback", "{}", seed, callbackSeed)
-			}
-		}
+func (self *UiLib) NewFilterString(typ string) int {
+	filter, id := self.eth.InstallFilter(nil)
+	filter.BlockCallback = func(block *ethchain.Block) {
+		self.win.Root().Call("invokeFilterCallback", "{}", id)
 	}
-}
 
-func (self *UiLib) RegisterFilterCallback(seed, cbSeed int) {
-	self.filterCallbacks[seed] = append(self.filterCallbacks[seed], cbSeed)
+	return id
 }
 
-func (self *UiLib) UninstallFilter(seed int) {
-	filter := self.filters[seed]
+func (self *UiLib) Messages(id int) *ethutil.List {
+	filter := self.eth.GetFilter(id)
 	if filter != nil {
-		filter.Uninstall()
-		delete(self.filters, seed)
+		messages := filter.Find()
+
+		return ethpipe.ToJSMessages(messages)
 	}
+
+	return ethutil.EmptyList()
 }
 
-type GuiFilter struct {
-	*ethpipe.JSFilter
-	seed int
+func (self *UiLib) UninstallFilter(id int) {
+	self.eth.UninstallFilter(id)
 }
 
-func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt, error) {
+func mapToTxParams(object map[string]interface{}) map[string]string {
 	// Default values
 	if object["from"] == nil {
 		object["from"] = ""
@@ -224,6 +222,8 @@ func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt,
 	var data []string
 	if list, ok := object["data"].(*qml.List); ok {
 		list.Convert(&data)
+	} else if str, ok := object["data"].(string); ok {
+		data = []string{str}
 	}
 
 	for _, str := range data {
@@ -239,13 +239,49 @@ func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt,
 
 		dataStr += str
 	}
+	object["data"] = dataStr
+	fmt.Println(object)
+
+	conv := make(map[string]string)
+	for key, value := range object {
+		if v, ok := value.(string); ok {
+			conv[key] = v
+		}
+	}
+
+	return conv
+}
+
+func (self *UiLib) Transact(params map[string]interface{}) (*ethpipe.JSReceipt, error) {
+	object := mapToTxParams(params)
 
 	return self.JSPipe.Transact(
-		object["from"].(string),
-		object["to"].(string),
-		object["value"].(string),
-		object["gas"].(string),
-		object["gasPrice"].(string),
-		dataStr,
+		object["from"],
+		object["to"],
+		object["value"],
+		object["gas"],
+		object["gasPrice"],
+		object["data"],
+	)
+}
+
+func (self *UiLib) Compile(code string) (string, error) {
+	bcode, err := ethutil.Compile(code, false)
+	if err != nil {
+		return err.Error(), err
+	}
+
+	return ethutil.Bytes2Hex(bcode), err
+}
+
+func (self *UiLib) Call(params map[string]interface{}) (string, error) {
+	object := mapToTxParams(params)
+
+	return self.JSPipe.Execute(
+		object["to"],
+		object["value"],
+		object["gas"],
+		object["gasPrice"],
+		object["data"],
 	)
 }
diff --git a/utils/cmd.go b/utils/cmd.go
index cda735c27d6e04d05fb3e6496787b0ee72c0bb11..700542cae42ee899e7d13640b23a4ee6f51c40b1 100644
--- a/utils/cmd.go
+++ b/utils/cmd.go
@@ -80,6 +80,16 @@ func confirm(message string) bool {
 	return r == "y"
 }
 
+func DBSanityCheck(db ethutil.Database) error {
+	d, _ := db.Get([]byte("ProtocolVersion"))
+	protov := ethutil.NewValue(d).Uint()
+	if protov != eth.ProtocolVersion && protov != 0 {
+		return fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, eth.ProtocolVersion, ethutil.Config.ExecPath+"/database")
+	}
+
+	return nil
+}
+
 func InitDataDir(Datadir string) {
 	_, err := os.Stat(Datadir)
 	if err != nil {
@@ -90,18 +100,22 @@ func InitDataDir(Datadir string) {
 	}
 }
 
-func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string) {
+func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string) ethlog.LogSystem {
 	var writer io.Writer
 	if LogFile == "" {
 		writer = os.Stdout
 	} else {
 		writer = openLogFile(Datadir, LogFile)
 	}
-	ethlog.AddLogSystem(ethlog.NewStdLogSystem(writer, log.LstdFlags, ethlog.LogLevel(LogLevel)))
+
+	sys := ethlog.NewStdLogSystem(writer, log.LstdFlags, ethlog.LogLevel(LogLevel))
+	ethlog.AddLogSystem(sys)
 	if DebugFile != "" {
 		writer = openLogFile(Datadir, DebugFile)
 		ethlog.AddLogSystem(ethlog.NewStdLogSystem(writer, log.LstdFlags, ethlog.DebugLevel))
 	}
+
+	return sys
 }
 
 func InitConfig(ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
@@ -112,7 +126,6 @@ func InitConfig(ConfigFile string, Datadir string, EnvPrefix string) *ethutil.Co
 func exit(err error) {
 	status := 0
 	if err != nil {
-		fmt.Println(err)
 		logger.Errorln("Fatal: ", err)
 		status = 1
 	}
@@ -176,7 +189,7 @@ func DefaultAssetPath() string {
 	// assume a debug build and use the source directory as
 	// asset directory.
 	pwd, _ := os.Getwd()
-	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
+	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist") {
 		assetPath = path.Join(pwd, "assets")
 	} else {
 		switch runtime.GOOS {
@@ -185,7 +198,7 @@ func DefaultAssetPath() string {
 			exedir, _ := osext.ExecutableFolder()
 			assetPath = filepath.Join(exedir, "../Resources")
 		case "linux":
-			assetPath = "/usr/share/ethereal"
+			assetPath = "/usr/share/mist"
 		case "windows":
 			assetPath = "./assets"
 		default: