Commit d1a6084b authored by obscuren's avatar obscuren

Merge branch 'release/0.6.8'

parents bd95fd77 a9b85776
...@@ -10,36 +10,41 @@ import ( ...@@ -10,36 +10,41 @@ import (
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
) )
var Identifier string var (
var KeyRing string Identifier string
var DiffTool bool KeyRing string
var DiffType string DiffTool bool
var KeyStore string DiffType string
var StartRpc bool KeyStore string
var RpcPort int StartRpc bool
var UseUPnP bool StartWebSockets bool
var OutboundPort string RpcPort int
var ShowGenesis bool UseUPnP bool
var AddPeer string OutboundPort string
var MaxPeer int ShowGenesis bool
var GenAddr bool AddPeer string
var UseSeed bool MaxPeer int
var SecretFile string GenAddr bool
var ExportDir string UseSeed bool
var NonInteractive bool SecretFile string
var Datadir string ExportDir string
var LogFile string NonInteractive bool
var ConfigFile string Datadir string
var DebugFile string LogFile string
var LogLevel int ConfigFile string
var Dump bool DebugFile string
var DumpHash string LogLevel int
var DumpNumber int Dump bool
DumpHash string
DumpNumber int
)
// flags specific to cli client // flags specific to cli client
var StartMining bool var (
var StartJsConsole bool StartMining bool
var InputFile string StartJsConsole bool
InputFile string
)
func defaultDataDir() string { func defaultDataDir() string {
usr, _ := user.Current() usr, _ := user.Current()
...@@ -62,6 +67,7 @@ func Init() { ...@@ -62,6 +67,7 @@ func Init() {
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
......
...@@ -103,6 +103,10 @@ func main() { ...@@ -103,6 +103,10 @@ func main() {
utils.StartRpc(ethereum, RpcPort) utils.StartRpc(ethereum, RpcPort)
} }
if StartWebSockets {
utils.StartWebSockets(ethereum)
}
utils.StartEthereum(ethereum, UseSeed) utils.StartEthereum(ethereum, UseSeed)
// this blocks the thread // this blocks the thread
......
// The magic return variable. The magic return variable will be set during the execution of the QML call. // The magic return variable. The magic return variable will be set during the execution of the QML call.
(function(window) { (function(window) {
function message(type, data) { var Promise = window.Promise;
document.title = JSON.stringify({type: type, data: data}); if(typeof(Promise) === "undefined") {
var Promise = Q.Promise;
return window.____returnData;
} }
function isPromise(o) { function isPromise(o) {
...@@ -446,6 +445,7 @@ ...@@ -446,6 +445,7 @@
} }
}); });
var g_seed = 1; var g_seed = 1;
function postData(data, cb) { function postData(data, cb) {
data._seed = g_seed; data._seed = g_seed;
...@@ -459,24 +459,6 @@ ...@@ -459,24 +459,6 @@
g_seed++; g_seed++;
navigator.qt.postMessage(JSON.stringify(data)); window._messagingAdapter.call(this, 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); })(this);
if(typeof(Promise) === "undefined") {
window.Promise = Q.Promise;
}
window._messagingAdapter = function(data) {
navigator.qt.postMessage(data);
};
navigator.qt.onmessage = function(ev) {
var data = JSON.parse(ev.data)
if(data._event !== undefined) {
eth.trigger(data._event, data.data);
} else {
if(data._seed) {
var cb = eth._callbacks[data._seed];
if(cb) {
cb.call(this, data.data)
// Remove the "trigger" callback
delete eth._callbacks[ev._seed];
}
}
}
}
...@@ -10,894 +10,902 @@ import "../ext/filter.js" as Eth ...@@ -10,894 +10,902 @@ import "../ext/filter.js" as Eth
import "../ext/http.js" as Http import "../ext/http.js" as Http
ApplicationWindow { ApplicationWindow {
id: root id: root
property alias miningButtonText: miningButton.text property alias miningButtonText: miningButton.text
property var ethx : Eth.ethx property var ethx : Eth.ethx
property var browser property var browser
width: 1200 width: 1200
height: 820 height: 820
minimumHeight: 300 minimumHeight: 300
title: "Mist" title: "Mist"
// This signal is used by the filter API. The filter API connects using this signal handler from // This signal is used by the filter API. The filter API connects using this signal handler from
// the different QML files and plugins. // the different QML files and plugins.
signal messages(var messages, int id); signal messages(var messages, int id);
function invokeFilterCallback(data, receiverSeed) { function invokeFilterCallback(data, receiverSeed) {
//var messages = JSON.parse(data) //var messages = JSON.parse(data)
// Signal handler // Signal handler
messages(data, receiverSeed); messages(data, receiverSeed);
root.browser.view.messages(data, receiverSeed); root.browser.view.messages(data, receiverSeed);
} }
TextField { TextField {
id: copyElementHax id: copyElementHax
visible: false visible: false
} }
function copyToClipboard(text) { function copyToClipboard(text) {
copyElementHax.text = text copyElementHax.text = text
copyElementHax.selectAll() copyElementHax.selectAll()
copyElementHax.copy() copyElementHax.copy()
} }
// Takes care of loading all default plugins // Takes care of loading all default plugins
Component.onCompleted: { Component.onCompleted: {
var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); 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}); var browser = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true});
root.browser = browser; root.browser = browser;
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/chain.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/info.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/pending_tx.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/javascript.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/jeffcoin/jeffcoin.qml", {noAdd: true, close: false, section: "apps"}) addPlugin("./views/jeffcoin/jeffcoin.qml", {noAdd: true, close: false, section: "apps"})
mainSplit.setView(wallet.view, wallet.menuItem); mainSplit.setView(wallet.view, wallet.menuItem);
// Call the ready handler // Call the ready handler
gui.done(); gui.done();
} }
function addViews(view, path, options) { function addViews(view, path, options) {
var views = mainSplit.addComponent(view, options) var views = mainSplit.addComponent(view, options)
views.menuItem.path = path views.menuItem.path = path
mainSplit.views.push(views); mainSplit.views.push(views);
if(!options.noAdd) { if(!options.noAdd) {
gui.addPlugin(path) gui.addPlugin(path)
} }
return views return views
} }
function addPlugin(path, options) { function addPlugin(path, options) {
try { try {
if(typeof(path) === "string" && /^https?/.test(path)) { if(typeof(path) === "string" && /^https?/.test(path)) {
console.log('load http') console.log('load http')
Http.request(path, function(o) { Http.request(path, function(o) {
if(o.status === 200) { if(o.status === 200) {
var view = Qt.createQmlObject(o.responseText, mainView, path) var view = Qt.createQmlObject(o.responseText, mainView, path)
addViews(view, path, options) addViews(view, path, options)
} }
}) })
return return
} }
var component = Qt.createComponent(path); var component = Qt.createComponent(path);
if(component.status != Component.Ready) { if(component.status != Component.Ready) {
if(component.status == Component.Error) { if(component.status == Component.Error) {
ethx.note("error: ", component.errorString()); ethx.note("error: ", component.errorString());
} }
return return
} }
var view = mainView.createView(component, options) var view = mainView.createView(component, options)
var views = addViews(view, path, options) var views = addViews(view, path, options)
return views return views
} catch(e) { } catch(e) {
ethx.note(e) ethx.note(e)
} }
} }
menuBar: MenuBar { menuBar: MenuBar {
Menu { Menu {
title: "File" title: "File"
MenuItem { MenuItem {
text: "Import App" text: "Import App"
shortcut: "Ctrl+o" shortcut: "Ctrl+o"
onTriggered: { onTriggered: {
generalFileDialog.show(true, importApp) generalFileDialog.show(true, importApp)
} }
} }
/* /*
MenuItem { MenuItem {
text: "Browser" text: "Browser"
onTriggered: eth.openBrowser() onTriggered: eth.openBrowser()
} }
*/ */
MenuItem { MenuItem {
text: "Add plugin" text: "Add plugin"
onTriggered: { onTriggered: {
generalFileDialog.show(true, function(path) { generalFileDialog.show(true, function(path) {
addPlugin(path, {close: true, section: "apps"}) addPlugin(path, {close: true, section: "apps"})
}) })
} }
} }
MenuSeparator {} MenuSeparator {}
MenuItem { MenuItem {
text: "Import key" text: "Import key"
shortcut: "Ctrl+i" shortcut: "Ctrl+i"
onTriggered: { onTriggered: {
generalFileDialog.show(true, function(path) { generalFileDialog.show(true, function(path) {
gui.importKey(path) gui.importKey(path)
}) })
} }
} }
MenuItem { MenuItem {
text: "Export keys" text: "Export keys"
shortcut: "Ctrl+e" shortcut: "Ctrl+e"
onTriggered: { onTriggered: {
generalFileDialog.show(false, function(path) { generalFileDialog.show(false, function(path) {
}) })
} }
} }
} }
Menu { Menu {
title: "Developer" title: "Developer"
MenuItem { MenuItem {
iconSource: "../icecream.png" iconSource: "../icecream.png"
text: "Debugger" text: "Debugger"
shortcut: "Ctrl+d" shortcut: "Ctrl+d"
onTriggered: eth.startDebugger() onTriggered: eth.startDebugger()
} }
MenuItem { MenuItem {
text: "Import Tx" text: "Import Tx"
onTriggered: { onTriggered: {
txImportDialog.visible = true txImportDialog.visible = true
} }
} }
MenuItem { MenuItem {
text: "Run JS file" text: "Run JS file"
onTriggered: { onTriggered: {
generalFileDialog.show(true, function(path) { generalFileDialog.show(true, function(path) {
eth.evalJavascriptFile(path) eth.evalJavascriptFile(path)
}) })
} }
} }
MenuItem { MenuItem {
text: "Dump state" text: "Dump state"
onTriggered: { onTriggered: {
generalFileDialog.show(false, function(path) { generalFileDialog.show(false, function(path) {
// Empty hash for latest // Empty hash for latest
gui.dumpState("", path) gui.dumpState("", path)
}) })
} }
} }
MenuSeparator {} MenuSeparator {}
/* /*
MenuItem { MenuItem {
id: miningSpeed id: miningSpeed
text: "Mining: Turbo" text: "Mining: Turbo"
onTriggered: { onTriggered: {
gui.toggleTurboMining() gui.toggleTurboMining()
if(text == "Mining: Turbo") { if(text == "Mining: Turbo") {
text = "Mining: Normal"; text = "Mining: Normal";
} else { } else {
text = "Mining: Turbo"; text = "Mining: Turbo";
} }
} }
} }
*/ */
} }
Menu { Menu {
title: "Network" title: "Network"
MenuItem { MenuItem {
text: "Add Peer" text: "Add Peer"
shortcut: "Ctrl+p" shortcut: "Ctrl+p"
onTriggered: { onTriggered: {
addPeerWin.visible = true addPeerWin.visible = true
} }
} }
MenuItem { MenuItem {
text: "Show Peers" text: "Show Peers"
shortcut: "Ctrl+e" shortcut: "Ctrl+e"
onTriggered: { onTriggered: {
peerWindow.visible = true peerWindow.visible = true
} }
} }
} }
Menu { Menu {
title: "Help" title: "Help"
MenuItem { MenuItem {
text: "About" text: "About"
onTriggered: { onTriggered: {
aboutWin.visible = true aboutWin.visible = true
} }
} }
} }
Menu { Menu {
title: "GLOBAL SHORTCUTS" title: "GLOBAL SHORTCUTS"
visible: false visible: false
MenuItem { MenuItem {
visible: false visible: false
shortcut: "Ctrl+l" shortcut: "Ctrl+l"
onTriggered: { onTriggered: {
url.focus = true url.focus = true
} }
} }
} }
} }
statusBar: StatusBar { statusBar: StatusBar {
height: 32 height: 32
id: statusBar id: statusBar
RowLayout { RowLayout {
Button { Button {
id: miningButton id: miningButton
text: "Start Mining" text: "Start Mining"
onClicked: { onClicked: {
gui.toggleMining() gui.toggleMining()
} }
} }
RowLayout { RowLayout {
Label { Label {
id: walletValueLabel id: walletValueLabel
font.pixelSize: 10 font.pixelSize: 10
styleColor: "#797979" styleColor: "#797979"
} }
} }
} }
Label { Label {
y: 6 y: 6
objectName: "miningLabel" objectName: "miningLabel"
visible: true visible: true
font.pixelSize: 10 font.pixelSize: 10
anchors.right: lastBlockLabel.left anchors.right: lastBlockLabel.left
anchors.rightMargin: 5 anchors.rightMargin: 5
} }
Label { Label {
y: 6 y: 6
id: lastBlockLabel id: lastBlockLabel
objectName: "lastBlockLabel" objectName: "lastBlockLabel"
visible: true visible: true
text: "" text: ""
font.pixelSize: 10 font.pixelSize: 10
anchors.right: peerGroup.left anchors.right: peerGroup.left
anchors.rightMargin: 5 anchors.rightMargin: 5
} }
ProgressBar { ProgressBar {
id: downloadIndicator id: downloadIndicator
value: 0 value: 0
visible: true objectName: "downloadIndicator"
objectName: "downloadIndicator" y: 3
y: 3 x: statusBar.width / 2 - this.width / 2
x: statusBar.width / 2 - this.width / 2 width: 160
width: 160 }
}
Label {
objectName: "downloadLabel"
RowLayout { y: 7
id: peerGroup anchors.left: downloadIndicator.right
y: 7 anchors.leftMargin: 5
anchors.right: parent.right font.pixelSize: 10
MouseArea { text: "0 / 0"
onDoubleClicked: peerWindow.visible = true }
anchors.fill: parent
}
RowLayout {
Label { id: peerGroup
id: peerLabel y: 7
font.pixelSize: 8 anchors.right: parent.right
text: "0 / 0" MouseArea {
} onDoubleClicked: peerWindow.visible = true
Image { anchors.fill: parent
id: peerImage }
width: 10; height: 10
source: "../network.png" Label {
} id: peerLabel
} font.pixelSize: 8
} text: "0 / 0"
}
Image {
property var blockModel: ListModel { id: peerImage
id: blockModel width: 10; height: 10
} source: "../network.png"
}
SplitView { }
property var views: []; }
id: mainSplit
anchors.fill: parent property var blockModel: ListModel {
resizing: false id: blockModel
}
function setView(view, menu) {
for(var i = 0; i < views.length; i++) { SplitView {
views[i].view.visible = false property var views: [];
views[i].menuItem.setSelection(false)
} id: mainSplit
view.visible = true anchors.fill: parent
resizing: false
//menu.border.color = "#CCCCCC"
//menu.color = "#FFFFFFFF" function setView(view, menu) {
menu.setSelection(true) for(var i = 0; i < views.length; i++) {
} views[i].view.visible = false
views[i].menuItem.setSelection(false)
function addComponent(view, options) { }
view.visible = false view.visible = true
view.anchors.fill = mainView
//menu.border.color = "#CCCCCC"
if( !view.hasOwnProperty("iconSource") ) { //menu.color = "#FFFFFFFF"
console.log("Could not load plugin. Property 'iconSourc' not found on view."); menu.setSelection(true)
return; }
}
function addComponent(view, options) {
var menuItem = menu.createMenuItem(view.iconSource, view, options); view.visible = false
if( view.hasOwnProperty("menuItem") ) { view.anchors.fill = mainView
view.menuItem = menuItem;
} if( !view.hasOwnProperty("iconSource") ) {
console.log("Could not load plugin. Property 'iconSourc' not found on view.");
if( view.hasOwnProperty("onReady") ) { return;
view.onReady.call(view) }
}
var menuItem = menu.createMenuItem(view.iconSource, view, options);
if( options.active ) { if( view.hasOwnProperty("menuItem") ) {
setView(view, menuItem) view.menuItem = menuItem;
} }
if( view.hasOwnProperty("onReady") ) {
return {view: view, menuItem: menuItem} view.onReady.call(view)
} }
/********************* if( options.active ) {
* Main menu. setView(view, menuItem)
********************/ }
Rectangle {
id: menu
Layout.minimumWidth: 210 return {view: view, menuItem: menuItem}
Layout.maximumWidth: 210 }
anchors.top: parent.top
color: "#ececec" /*********************
* Main menu.
Component { ********************/
id: menuItemTemplate Rectangle {
Rectangle { id: menu
id: menuItem Layout.minimumWidth: 210
property var view; Layout.maximumWidth: 210
property var path; anchors.top: parent.top
property var closable; color: "#ececec"
property alias title: label.text Component {
property alias icon: icon.source id: menuItemTemplate
property alias secondaryTitle: secondary.text Rectangle {
function setSelection(on) { id: menuItem
sel.visible = on property var view;
} property var path;
property var closable;
width: 206
height: 28 property alias title: label.text
color: "#00000000" property alias icon: icon.source
property alias secondaryTitle: secondary.text
anchors { function setSelection(on) {
left: parent.left sel.visible = on
leftMargin: 4 }
}
width: 206
Rectangle { height: 28
id: sel color: "#00000000"
visible: false
anchors.fill: parent anchors {
color: "#00000000" left: parent.left
Rectangle { leftMargin: 4
id: r }
anchors.fill: parent
border.color: "#CCCCCC" Rectangle {
border.width: 1 id: sel
radius: 5 visible: false
color: "#FFFFFFFF" anchors.fill: parent
} color: "#00000000"
Rectangle { Rectangle {
anchors { id: r
top: r.top anchors.fill: parent
bottom: r.bottom border.color: "#CCCCCC"
right: r.right border.width: 1
} radius: 5
width: 10 color: "#FFFFFFFF"
color: "#FFFFFFFF" }
Rectangle {
Rectangle { anchors {
anchors { top: r.top
left: parent.left bottom: r.bottom
right: parent.right right: r.right
top: parent.top }
} width: 10
height: 1 color: "#FFFFFFFF"
color: "#CCCCCC"
} Rectangle {
anchors {
Rectangle { left: parent.left
anchors { right: parent.right
left: parent.left top: parent.top
right: parent.right }
bottom: parent.bottom height: 1
} color: "#CCCCCC"
height: 1 }
color: "#CCCCCC"
} Rectangle {
} anchors {
} left: parent.left
right: parent.right
MouseArea { bottom: parent.bottom
anchors.fill: parent }
onClicked: { height: 1
mainSplit.setView(view, menuItem) color: "#CCCCCC"
} }
} }
}
Image {
id: icon MouseArea {
height: 20 anchors.fill: parent
width: 20 onClicked: {
anchors { mainSplit.setView(view, menuItem)
left: parent.left }
verticalCenter: parent.verticalCenter }
leftMargin: 3
} Image {
MouseArea { id: icon
anchors.fill: parent height: 20
onClicked: { width: 20
menuItem.closeApp() anchors {
} left: parent.left
} verticalCenter: parent.verticalCenter
} leftMargin: 3
}
Text { MouseArea {
id: label anchors.fill: parent
anchors { onClicked: {
left: icon.right menuItem.closeApp()
verticalCenter: parent.verticalCenter }
leftMargin: 3 }
} }
color: "#0D0A01" Text {
font.pixelSize: 12 id: label
} anchors {
left: icon.right
Text { verticalCenter: parent.verticalCenter
id: secondary leftMargin: 3
anchors { }
right: parent.right
rightMargin: 8 color: "#0D0A01"
verticalCenter: parent.verticalCenter font.pixelSize: 12
} }
color: "#AEADBE"
font.pixelSize: 12 Text {
} id: secondary
anchors {
right: parent.right
function closeApp() { rightMargin: 8
if(!this.closable) { return; } verticalCenter: parent.verticalCenter
}
if(this.view.hasOwnProperty("onDestroy")) { color: "#AEADBE"
this.view.onDestroy.call(this.view) font.pixelSize: 12
} }
this.view.destroy()
this.destroy() function closeApp() {
gui.removePlugin(this.path) if(!this.closable) { return; }
}
} if(this.view.hasOwnProperty("onDestroy")) {
} this.view.onDestroy.call(this.view)
}
function createMenuItem(icon, view, options) {
if(options === undefined) { this.view.destroy()
options = {}; this.destroy()
} gui.removePlugin(this.path)
}
var section; }
switch(options.section) { }
case "ethereum":
section = menuDefault; function createMenuItem(icon, view, options) {
break; if(options === undefined) {
case "legacy": options = {};
section = menuLegacy; }
break;
default: var section;
section = menuApps; switch(options.section) {
break; case "ethereum":
} section = menuDefault;
break;
var comp = menuItemTemplate.createObject(section) case "legacy":
section = menuLegacy;
comp.view = view break;
comp.title = view.title default:
comp.icon = view.iconSource section = menuApps;
comp.closable = options.close; break;
}
return comp
} var comp = menuItemTemplate.createObject(section)
ColumnLayout { comp.view = view
id: menuColumn comp.title = view.title
y: 10 comp.icon = view.iconSource
width: parent.width comp.closable = options.close;
anchors.left: parent.left
anchors.right: parent.right return comp
spacing: 3 }
Text { ColumnLayout {
text: "ETHEREUM" id: menuColumn
font.bold: true y: 10
anchors { width: parent.width
left: parent.left anchors.left: parent.left
leftMargin: 5 anchors.right: parent.right
} spacing: 3
color: "#888888"
} Text {
text: "ETHEREUM"
ColumnLayout { font.bold: true
id: menuDefault anchors {
spacing: 3 left: parent.left
anchors { leftMargin: 5
left: parent.left }
right: parent.right color: "#888888"
} }
}
ColumnLayout {
id: menuDefault
Text { spacing: 3
text: "APPS" anchors {
font.bold: true left: parent.left
anchors { right: parent.right
left: parent.left }
leftMargin: 5 }
}
color: "#888888"
} Text {
text: "APPS"
ColumnLayout { font.bold: true
id: menuApps anchors {
spacing: 3 left: parent.left
anchors { leftMargin: 5
left: parent.left }
right: parent.right color: "#888888"
} }
}
ColumnLayout {
Text { id: menuApps
text: "DEBUG" spacing: 3
font.bold: true anchors {
anchors { left: parent.left
left: parent.left right: parent.right
leftMargin: 5 }
} }
color: "#888888"
} Text {
text: "DEBUG"
ColumnLayout { font.bold: true
id: menuLegacy anchors {
spacing: 3 left: parent.left
anchors { leftMargin: 5
left: parent.left }
right: parent.right color: "#888888"
} }
}
} ColumnLayout {
} id: menuLegacy
spacing: 3
/********************* anchors {
* Main view left: parent.left
********************/ right: parent.right
Rectangle { }
anchors.right: parent.right }
anchors.left: menu.right }
anchors.bottom: parent.bottom }
anchors.top: parent.top
color: "#00000000" /*********************
* Main view
Rectangle { ********************/
id: urlPane Rectangle {
height: 40 anchors.right: parent.right
color: "#00000000" anchors.left: menu.right
anchors { anchors.bottom: parent.bottom
left: parent.left anchors.top: parent.top
right: parent.right color: "#00000000"
leftMargin: 5
rightMargin: 5 Rectangle {
top: parent.top id: urlPane
topMargin: 5 height: 40
} color: "#00000000"
TextField { anchors {
id: url left: parent.left
objectName: "url" right: parent.right
placeholderText: "DApp URL" leftMargin: 5
anchors { rightMargin: 5
left: parent.left top: parent.top
right: parent.right topMargin: 5
top: parent.top }
topMargin: 5 TextField {
rightMargin: 5 id: url
leftMargin: 5 objectName: "url"
} placeholderText: "DApp URL"
anchors {
Keys.onReturnPressed: { left: parent.left
if(/^https?/.test(this.text)) { right: parent.right
root.browser.view.open(this.text); top: parent.top
mainSplit.setView(root.browser.view, root.browser.menuItem); topMargin: 5
} else { rightMargin: 5
addPlugin(this.text, {close: true, section: "apps"}) leftMargin: 5
} }
}
} Keys.onReturnPressed: {
if(/^https?/.test(this.text)) {
} root.browser.view.open(this.text);
mainSplit.setView(root.browser.view, root.browser.menuItem);
// Border } else {
Rectangle { addPlugin(this.text, {close: true, section: "apps"})
id: divider }
anchors { }
left: parent.left }
right: parent.right
top: urlPane.bottom }
}
z: -1 // Border
height: 1 Rectangle {
color: "#CCCCCC" id: divider
} anchors {
left: parent.left
Rectangle { right: parent.right
id: mainView top: urlPane.bottom
color: "#00000000" }
anchors.right: parent.right z: -1
anchors.left: parent.left height: 1
anchors.bottom: parent.bottom color: "#CCCCCC"
anchors.top: divider.bottom }
function createView(component) { Rectangle {
var view = component.createObject(mainView) id: mainView
color: "#00000000"
return view; anchors.right: parent.right
} anchors.left: parent.left
} anchors.bottom: parent.bottom
} anchors.top: divider.bottom
}
function createView(component) {
var view = component.createObject(mainView)
/******************
* Dialogs return view;
*****************/ }
FileDialog { }
id: generalFileDialog }
property var callback; }
onAccepted: {
var path = this.fileUrl.toString();
callback.call(this, path); /******************
} * Dialogs
*****************/
function show(selectExisting, callback) { FileDialog {
generalFileDialog.callback = callback; id: generalFileDialog
generalFileDialog.selectExisting = selectExisting; property var callback;
onAccepted: {
this.open(); var path = this.fileUrl.toString();
} callback.call(this, path);
} }
function show(selectExisting, callback) {
/****************** generalFileDialog.callback = callback;
* Wallet functions generalFileDialog.selectExisting = selectExisting;
*****************/
function importApp(path) { this.open();
var ext = path.split('.').pop() }
if(ext == "html" || ext == "htm") { }
eth.openHtml(path)
}else if(ext == "qml"){
addPlugin(path, {close: true, section: "apps"}) /******************
} * Wallet functions
} *****************/
function importApp(path) {
var ext = path.split('.').pop()
function setWalletValue(value) { if(ext == "html" || ext == "htm") {
walletValueLabel.text = value eth.openHtml(path)
} }else if(ext == "qml"){
addPlugin(path, {close: true, section: "apps"})
function loadPlugin(name) { }
console.log("Loading plugin" + name) }
var view = mainView.addPlugin(name)
}
function setWalletValue(value) {
function setPeers(text) { walletValueLabel.text = value
peerLabel.text = text }
}
function loadPlugin(name) {
function addPeer(peer) { console.log("Loading plugin" + name)
// We could just append the whole peer object but it cries if you try to alter them var view = mainView.addPlugin(name)
peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version, caps: peer.caps}) }
}
function setPeers(text) {
function resetPeers(){ peerLabel.text = text
peerModel.clear() }
}
function addPeer(peer) {
function timeAgo(unixTs){ // We could just append the whole peer object but it cries if you try to alter them
var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000 peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version, caps: peer.caps})
return (lapsed + " seconds ago") }
}
function resetPeers(){
function convertToPretty(unixTs){ peerModel.clear()
var a = new Date(unixTs*1000); }
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear(); function timeAgo(unixTs){
var month = months[a.getMonth()]; var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000
var date = a.getDate(); return (lapsed + " seconds ago")
var hour = a.getHours(); }
var min = a.getMinutes();
var sec = a.getSeconds(); function convertToPretty(unixTs){
var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; var a = new Date(unixTs*1000);
return time; 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();
* Windows var hour = a.getHours();
*********************/ var min = a.getMinutes();
Window { var sec = a.getSeconds();
id: peerWindow var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ;
//flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint return time;
height: 200 }
width: 700
Rectangle { /**********************
anchors.fill: parent * Windows
property var peerModel: ListModel { *********************/
id: peerModel Window {
} id: peerWindow
TableView { //flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
anchors.fill: parent height: 200
id: peerTable width: 700
model: peerModel Rectangle {
TableViewColumn{width: 100; role: "ip" ; title: "IP" } anchors.fill: parent
TableViewColumn{width: 60; role: "port" ; title: "Port" } property var peerModel: ListModel {
TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } id: peerModel
TableViewColumn{width: 100; role: "latency"; title: "Latency" } }
TableViewColumn{width: 260; role: "version" ; title: "Version" } TableView {
TableViewColumn{width: 80; role: "caps" ; title: "Capabilities" } anchors.fill: parent
} id: peerTable
} model: peerModel
} TableViewColumn{width: 100; role: "ip" ; title: "IP" }
TableViewColumn{width: 60; role: "port" ; title: "Port" }
Window { TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" }
id: aboutWin TableViewColumn{width: 100; role: "latency"; title: "Latency" }
visible: false TableViewColumn{width: 260; role: "version" ; title: "Version" }
title: "About" TableViewColumn{width: 80; role: "caps" ; title: "Capabilities" }
minimumWidth: 350 }
maximumWidth: 350 }
maximumHeight: 200 }
minimumHeight: 200
Window {
Image { id: aboutWin
id: aboutIcon visible: false
height: 150 title: "About"
width: 150 minimumWidth: 350
fillMode: Image.PreserveAspectFit maximumWidth: 350
smooth: true maximumHeight: 200
source: "../facet.png" minimumHeight: 200
x: 10
y: 10 Image {
} id: aboutIcon
height: 150
Text { width: 150
anchors.left: aboutIcon.right fillMode: Image.PreserveAspectFit
anchors.leftMargin: 10 smooth: true
anchors.top: parent.top source: "../facet.png"
anchors.topMargin: 30 x: 10
font.pointSize: 12 y: 10
text: "<h2>Mist (0.6.5)</h2><h4>Amalthea</h4><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br><h3>Building</h3>Maran Hidskes" }
}
} Text {
anchors.left: aboutIcon.right
Window { anchors.leftMargin: 10
id: txImportDialog anchors.top: parent.top
minimumWidth: 270 anchors.topMargin: 30
maximumWidth: 270 font.pointSize: 12
maximumHeight: 50 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"
minimumHeight: 50 }
TextField { }
id: txImportField
width: 170 Window {
anchors.verticalCenter: parent.verticalCenter id: txImportDialog
anchors.left: parent.left minimumWidth: 270
anchors.leftMargin: 10 maximumWidth: 270
onAccepted: { maximumHeight: 50
} minimumHeight: 50
} TextField {
Button { id: txImportField
anchors.left: txImportField.right width: 170
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 5 anchors.left: parent.left
text: "Import" anchors.leftMargin: 10
onClicked: { onAccepted: {
eth.importTx(txImportField.text) }
txImportField.visible = false }
} Button {
} anchors.left: txImportField.right
Component.onCompleted: { anchors.verticalCenter: parent.verticalCenter
addrField.focus = true anchors.leftMargin: 5
} text: "Import"
} onClicked: {
eth.importTx(txImportField.text)
Window { txImportField.visible = false
id: addPeerWin }
visible: false }
minimumWidth: 300 Component.onCompleted: {
maximumWidth: 300 addrField.focus = true
maximumHeight: 50 }
minimumHeight: 50 }
title: "Connect to peer"
Window {
ComboBox { id: addPeerWin
id: addrField visible: false
anchors.verticalCenter: parent.verticalCenter minimumWidth: 300
anchors.left: parent.left maximumWidth: 300
anchors.right: addPeerButton.left maximumHeight: 50
anchors.leftMargin: 10 minimumHeight: 50
anchors.rightMargin: 10 title: "Connect to peer"
onAccepted: {
eth.connectToPeer(addrField.currentText) ComboBox {
addPeerWin.visible = false id: addrField
} anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
editable: true anchors.right: addPeerButton.left
model: ListModel { id: pastPeers } anchors.leftMargin: 10
anchors.rightMargin: 10
Component.onCompleted: { onAccepted: {
var ips = eth.pastPeers() eth.connectToPeer(addrField.currentText)
for(var i = 0; i < ips.length; i++) { addPeerWin.visible = false
pastPeers.append({text: ips.get(i)}) }
}
editable: true
pastPeers.insert(0, {text: "poc-6.ethdev.com:30303"}) model: ListModel { id: pastPeers }
}
} Component.onCompleted: {
var ips = eth.pastPeers()
Button { for(var i = 0; i < ips.length; i++) {
id: addPeerButton pastPeers.append({text: ips.get(i)})
anchors.right: parent.right }
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10 pastPeers.insert(0, {text: "poc-6.ethdev.com:30303"})
text: "Add" }
onClicked: { }
eth.connectToPeer(addrField.currentText)
addPeerWin.visible = false Button {
} id: addPeerButton
} anchors.right: parent.right
Component.onCompleted: { anchors.verticalCenter: parent.verticalCenter
addrField.focus = true anchors.rightMargin: 10
} text: "Add"
} onClicked: {
eth.connectToPeer(addrField.currentText)
addPeerWin.visible = false
}
}
Component.onCompleted: {
addrField.focus = true
}
}
} }
...@@ -164,7 +164,7 @@ import "../ext/qml_messaging.js" as Messaging ...@@ -164,7 +164,7 @@ import "../ext/qml_messaging.js" as Messaging
experimental.preferences.javascriptEnabled: true experimental.preferences.javascriptEnabled: true
experimental.preferences.navigatorQtObjectEnabled: true experimental.preferences.navigatorQtObjectEnabled: true
experimental.preferences.developerExtrasEnabled: true experimental.preferences.developerExtrasEnabled: true
experimental.userScripts: ["../ext/q.js", "../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"] experimental.userScripts: ["../ext/qt_messaging_adapter.js", "../ext/q.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"]
experimental.onMessageReceived: { experimental.onMessageReceived: {
console.log("[onMessageReceived]: ", message.data) console.log("[onMessageReceived]: ", message.data)
// TODO move to messaging.js // TODO move to messaging.js
......
...@@ -271,7 +271,8 @@ func (gui *Gui) loadAddressBook() { ...@@ -271,7 +271,8 @@ func (gui *Gui) loadAddressBook() {
} }
func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) { func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
nameReg := ethpipe.New(gui.eth).World().Config().Get("NameReg") pipe := ethpipe.New(gui.eth)
nameReg := pipe.World().Config().Get("NameReg")
addr := gui.address() addr := gui.address()
var inout string var inout string
...@@ -282,14 +283,14 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) { ...@@ -282,14 +283,14 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
} }
var ( var (
ptx = ethpipe.NewJSTx(tx) ptx = ethpipe.NewJSTx(tx, pipe.World().State())
send = nameReg.Storage(tx.Sender()) send = nameReg.Storage(tx.Sender())
rec = nameReg.Storage(tx.Recipient) rec = nameReg.Storage(tx.Recipient)
s, r string s, r string
) )
if tx.CreatesContract() { if tx.CreatesContract() {
rec = nameReg.Storage(tx.CreationAddress()) rec = nameReg.Storage(tx.CreationAddress(pipe.World().State()))
} }
if send.Len() != 0 { if send.Len() != 0 {
...@@ -301,7 +302,7 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) { ...@@ -301,7 +302,7 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
r = strings.Trim(rec.Str(), "\x00") r = strings.Trim(rec.Str(), "\x00")
} else { } else {
if tx.CreatesContract() { if tx.CreatesContract() {
r = ethutil.Bytes2Hex(tx.CreationAddress()) r = ethutil.Bytes2Hex(tx.CreationAddress(pipe.World().State()))
} else { } else {
r = ethutil.Bytes2Hex(tx.Recipient) r = ethutil.Bytes2Hex(tx.Recipient)
} }
...@@ -466,13 +467,11 @@ func (gui *Gui) update() { ...@@ -466,13 +467,11 @@ func (gui *Gui) update() {
var ( var (
pct float64 = 1.0 / float64(chainLength) * float64(blockLength) pct float64 = 1.0 / float64(chainLength) * float64(blockLength)
dlWidget = gui.win.Root().ObjectByName("downloadIndicator") dlWidget = gui.win.Root().ObjectByName("downloadIndicator")
dlLabel = gui.win.Root().ObjectByName("downloadLabel")
) )
if pct < 1.0 {
dlWidget.Set("visible", true) dlWidget.Set("value", pct)
dlWidget.Set("value", pct) dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
} else {
dlWidget.Set("visible", false)
}
case <-statsUpdateTicker.C: case <-statsUpdateTicker.C:
gui.setStatsPane() gui.setStatsPane()
...@@ -500,7 +499,7 @@ func (gui *Gui) setStatsPane() { ...@@ -500,7 +499,7 @@ func (gui *Gui) setStatsPane() {
runtime.ReadMemStats(&memStats) runtime.ReadMemStats(&memStats)
statsPane := gui.getObjectByName("statsPane") statsPane := gui.getObjectByName("statsPane")
statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.7 (%s) ####### statsPane.Set("text", fmt.Sprintf(`###### Mist 0.6.8 (%s) #######
eth %d (p2p = %d) eth %d (p2p = %d)
......
package utils
import (
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethpipe"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/websocket"
)
func args(v ...interface{}) []interface{} {
return v
}
type WebSocketServer struct {
ethereum *eth.Ethereum
filterCallbacks map[int][]int
}
func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
return &WebSocketServer{eth, make(map[int][]int)}
}
func (self *WebSocketServer) Serv() {
pipe := ethpipe.NewJSPipe(self.ethereum)
wsServ := websocket.NewServer("/eth", ":40404")
wsServ.MessageFunc(func(c *websocket.Client, msg *websocket.Message) {
switch msg.Call {
case "compile":
data := ethutil.NewValue(msg.Args)
bcode, err := ethutil.Compile(data.Get(0).Str(), false)
if err != nil {
c.Write(args(nil, err.Error()), msg.Seed)
}
code := ethutil.Bytes2Hex(bcode)
c.Write(args(code, nil), msg.Seed)
case "getBlockByNumber":
args := msg.Arguments()
block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
c.Write(block, msg.Seed)
case "getKey":
c.Write(pipe.Key().PrivateKey, msg.Seed)
case "transact":
if mp, ok := msg.Args[0].(map[string]interface{}); ok {
object := mapToTxParams(mp)
c.Write(
args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])),
msg.Seed,
)
}
case "getCoinBase":
c.Write(pipe.CoinBase(), msg.Seed)
case "getIsListening":
c.Write(pipe.IsListening(), msg.Seed)
case "getIsMining":
c.Write(pipe.IsMining(), msg.Seed)
case "getPeerCoint":
c.Write(pipe.PeerCount(), msg.Seed)
case "getCountAt":
args := msg.Arguments()
c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Seed)
case "getCodeAt":
args := msg.Arguments()
c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Seed)
case "getBlockByHash":
args := msg.Arguments()
c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Seed)
case "getStorageAt":
args := msg.Arguments()
c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Seed)
case "getBalanceAt":
args := msg.Arguments()
c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Seed)
case "getSecretToAddress":
args := msg.Arguments()
c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Seed)
case "newFilter":
case "newFilterString":
case "messages":
// TODO
}
})
wsServ.Listen()
}
func StartWebSockets(eth *eth.Ethereum) {
sock := NewWebSocketServer(eth)
go sock.Serv()
}
// TODO This is starting to become a generic method. Move to utils
func mapToTxParams(object map[string]interface{}) map[string]string {
// Default values
if object["from"] == nil {
object["from"] = ""
}
if object["to"] == nil {
object["to"] = ""
}
if object["value"] == nil {
object["value"] = ""
}
if object["gas"] == nil {
object["gas"] = ""
}
if object["gasPrice"] == nil {
object["gasPrice"] = ""
}
var dataStr string
var data []string
if str, ok := object["data"].(string); ok {
data = []string{str}
}
for _, str := range data {
if ethutil.IsHex(str) {
str = str[2:]
if len(str) != 64 {
str = ethutil.LeftPadString(str, 64)
}
} else {
str = ethutil.Bytes2Hex(ethutil.LeftPadBytes(ethutil.Big(str).Bytes(), 32))
}
dataStr += str
}
object["data"] = dataStr
conv := make(map[string]string)
for key, value := range object {
if v, ok := value.(string); ok {
conv[key] = v
}
}
return conv
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment