Tweaks and fixes + added webview debugger

* Require better icons .. someone? :-)
This commit is contained in:
obscuren 2014-08-14 00:18:37 +02:00
parent d518423b9c
commit 95ba340d07
14 changed files with 271 additions and 260 deletions

BIN
ethereal/assets/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
ethereal/assets/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

View File

@ -2,30 +2,97 @@
window.eth = { window.eth = {
prototype: Object(), prototype: Object(),
mutan: function(code) {
},
toHex: function(str) {
var hex = "";
for(var i = 0; i < str.length; i++) {
var n = str.charCodeAt(i).toString(16);
hex += n.length < 2 ? '0' + n : n;
}
return hex;
},
toAscii: function(hex) {
// Find termination
var str = "";
var i = 0, l = hex.length;
for(; i < l; i+=2) {
var code = hex.charCodeAt(i)
if(code == 0) {
break;
}
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
}
return str;
},
fromAscii: function(str, pad) {
if(pad === undefined) {
pad = 32
}
var hex = this.toHex(str);
while(hex.length < pad*2)
hex += "00";
return hex
},
// Retrieve block // Retrieve block
// //
// Either supply a number or a string. Type is determent for the lookup method // Either supply a number or a string. Type is determent for the lookup method
// string - Retrieves the block by looking up the hash // string - Retrieves the block by looking up the hash
// number - Retrieves the block by looking up the block number // number - Retrieves the block by looking up the block number
getBlock: function(numberOrHash, cb) { getBlock: function(numberOrHash, cb) {
var func; var func;
if(typeof numberOrHash == "string") { if(typeof numberOrHash == "string") {
func = "getBlockByHash"; func = "getBlockByHash";
} else { } else {
func = "getBlockByNumber"; func = "getBlockByNumber";
} }
postData({call: func, args: [numberOrHash]}, cb); postData({call: func, args: [numberOrHash]}, cb);
}, },
// Create transaction // Create transaction
// //
// Transact between two state objects // Transact between two state objects
transact: function(sec, recipient, value, gas, gasPrice, data, cb) { transact: function(params, cb) {
postData({call: "transact", args: [sec, recipient, value, gas, gasPrice, data]}, cb); if(params === undefined) {
}, params = {};
}
create: function(sec, value, gas, gasPrice, init, body, cb) { if(params.endowment !== undefined)
postData({call: "create", args: [sec, value, gas, gasPrice, init, body]}, cb); params.value = params.endowment;
if(params.code !== undefined)
params.data = params.code;
// Make sure everything is string
var fields = ["to", "from", "value", "gas", "gasPrice"];
for(var i = 0; i < fields.length; i++) {
if(params[fields[i]] === undefined) {
params[fields[i]] = "";
}
params[fields[i]] = params[fields[i]].toString();
}
var data;
if(typeof params.data === "object") {
data = "";
for(var i = 0; i < params.data.length; i++) {
data += params.data[i]
}
} else {
data = params.data;
}
postData({call: "transact", args: [params.from, params.to, params.value, params.gas, params.gasPrice, "0x"+data]}, cb);
}, },
getStorageAt: function(address, storageAddress, cb) { getStorageAt: function(address, storageAddress, cb) {

View File

@ -1,117 +0,0 @@
function handleMessage(message) {
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.getCoinBase())
break
case "getIsListening":
postData(data._seed, eth.getIsListening())
break
case "getIsMining":
postData(data._seed, eth.getIsMining())
break
case "getPeerCount":
postData(data._seed, eth.getPeerCount())
break
case "getTxCountAt":
require(1)
postData(data._seed, eth.getTxCountAt(data.args[0]))
break
case "getBlockByNumber":
var block = eth.getBlock(data.args[0])
postData(data._seed, block)
break
case "getBlockByHash":
var block = eth.getBlock(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 "create":
postData(data._seed, null)
break
case "getStorage":
require(2);
var stateObject = eth.getStateObject(data.args[0])
var storage = stateObject.getStorage(data.args[1])
postData(data._seed, storage)
break
case "getStateKeyVals":
require(1);
var stateObject = eth.getStateObject(data.args[0]).stateKeyVal(true)
postData(data._seed,stateObject)
break
case "getTransactionsFor":
require(1);
var txs = eth.getTransactionsFor(data.args[0], true)
postData(data._seed, txs)
break
case "getBalance":
require(1);
postData(data._seed, eth.getStateObject(data.args[0]).value());
break
case "getKey":
var key = eth.getKey().privateKey;
postData(data._seed, key)
break
case "watch":
require(1)
eth.watch(data.args[0], data.args[1]);
break
case "disconnect":
require(1)
postData(data._seed, null)
break;
case "set":
console.log("'Set' has been depcrecated")
/*
for(var key in data.args) {
if(webview.hasOwnProperty(key)) {
window[key] = data.args[key];
}
}
*/
break;
case "getSecretToAddress":
require(1)
postData(data._seed, eth.secretToAddress(data.args[0]))
break;
case "debug":
console.log(data.args[0]);
break;
}
} catch(e) {
console.log(data.call + ": " + e)
postData(data._seed, null);
}
}
function postData(seed, data) {
webview.experimental.postMessage(JSON.stringify({data: data, _seed: seed}))
}

BIN
ethereal/assets/pick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

View File

@ -29,7 +29,7 @@ Rectangle {
model: txModel model: txModel
} }
function addTx(type, tx, inout) { function addTx(tx, inout) {
var isContract var isContract
if (tx.contract == true){ if (tx.contract == true){
isContract = "Yes" isContract = "Yes"

View File

@ -17,6 +17,7 @@ Rectangle {
color: "#00000000" color: "#00000000"
Column { Column {
id: info
spacing: 3 spacing: 3
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 5 anchors.topMargin: 5
@ -49,7 +50,7 @@ Rectangle {
} }
TableView { TableView {
id: addressView id: addressView
width: parent.width - 200 width: parent.width
height: 200 height: 200
anchors.bottom: logLayout.top anchors.bottom: logLayout.top
TableViewColumn{ role: "name"; title: "name" } TableViewColumn{ role: "name"; title: "name" }
@ -58,30 +59,6 @@ Rectangle {
model: addressModel model: addressModel
} }
Rectangle {
anchors.top: addressView.top
anchors.left: addressView.right
anchors.leftMargin: 20
TextField {
placeholderText: "Name to register"
id: nameToReg
width: 150
}
Button {
anchors.top: nameToReg.bottom
text: "Register"
MouseArea{
anchors.fill: parent
onClicked: {
gui.registerName(nameToReg.text)
nameToReg.text = ""
}
}
}
}
property var logModel: ListModel { property var logModel: ListModel {
id: logModel id: logModel
} }

View File

@ -0,0 +1,45 @@
import QtQuick 2.0
import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import QtQuick.Dialogs 1.0;
import QtQuick.Window 2.1;
import QtQuick.Controls.Styles 1.1
import Ethereum 1.0
Rectangle {
property var title: "JavaScript"
property var iconFile: "../tx.png"
objectName: "javascriptView"
visible: false
anchors.fill: parent
TextField {
id: input
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: 20
Keys.onReturnPressed: {
var res = eth.evalJavascriptString(this.text);
this.text = "";
output.append(res)
}
}
TextArea {
id: output
verticalAlignment: TextEdit.AlignBottom
text: "> JSRE Ready..."
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: input.top
}
}
}

View File

@ -30,7 +30,7 @@ Rectangle {
model: pendingTxModel model: pendingTxModel
} }
function addTx(type, tx, inout) { function addTx(tx, inout) {
var isContract var isContract
if (tx.contract == true){ if (tx.contract == true){
isContract = "Yes" isContract = "Yes"

View File

@ -24,6 +24,7 @@ ApplicationWindow {
var chainView = addPlugin("./views/chain.qml", {title: "Block chain"}) var chainView = addPlugin("./views/chain.qml", {title: "Block chain"})
var infoView = addPlugin("./views/info.qml", {title: "Info"}) var infoView = addPlugin("./views/info.qml", {title: "Info"})
var pendingTxView = addPlugin("./views/pending_tx.qml", {title: "Pending", canClose: true}) var pendingTxView = addPlugin("./views/pending_tx.qml", {title: "Pending", canClose: true})
var pendingTxView = addPlugin("./views/javascript.qml", {title: "JavaScript", canClose: true})
// Call the ready handler // Call the ready handler
gui.done() gui.done()
@ -259,8 +260,8 @@ ApplicationWindow {
********************/ ********************/
Rectangle { Rectangle {
id: menu id: menu
Layout.minimumWidth: 180 Layout.minimumWidth: 80
Layout.maximumWidth: 180 Layout.maximumWidth: 80
anchors.top: parent.top anchors.top: parent.top
color: "#252525" color: "#252525"
@ -398,9 +399,9 @@ ApplicationWindow {
function importApp(path) { function importApp(path) {
var ext = path.split('.').pop() var ext = path.split('.').pop()
if(ext == "html" || ext == "htm") { if(ext == "html" || ext == "htm") {
ui.openHtml(path) eth.openHtml(path)
}else if(ext == "qml"){ }else if(ext == "qml"){
ui.openQml(path) eth.openQml(path)
} }
} }

View File

@ -21,46 +21,62 @@ ApplicationWindow {
id: root id: root
anchors.fill: parent anchors.fill: parent
state: "inspectorShown" state: "inspectorShown"
TextField {
RowLayout {
id: navBar
anchors { anchors {
top: parent.top
left: parent.left left: parent.left
right: parent.right right: parent.right
} }
id: uriNav
//text: webview.url
Keys.onReturnPressed: { Button {
var uri = this.text; id: back
if(!/.*\:\/\/.*/.test(uri)) { iconSource: "../back.png"
uri = "http://" + uri; onClicked: {
webview.goBack()
} }
}
var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ TextField {
anchors {
if(reg.test(uri)) { top: parent.top
this.text.replace(reg, function(match, pre, domain, path) { left: back.right
uri = pre; right: parent.right
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;
});
} }
id: uriNav
console.log("connecting to ...", uri) Keys.onReturnPressed: {
var uri = this.text;
if(!/.*\:\/\/.*/.test(uri)) {
uri = "http://" + uri;
}
webview.url = uri; var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/
if(reg.test(uri)) {
this.text.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;
});
}
console.log("connecting to ...", uri)
webview.url = uri;
}
} }
} }
@ -71,7 +87,7 @@ ApplicationWindow {
left: parent.left left: parent.left
right: parent.right right: parent.right
bottom: parent.bottom bottom: parent.bottom
top: uriNav.bottom top: navBar.bottom
} }
onTitleChanged: { window.title = title } onTitleChanged: { window.title = title }
experimental.preferences.javascriptEnabled: true experimental.preferences.javascriptEnabled: true
@ -86,103 +102,107 @@ ApplicationWindow {
try { try {
switch(data.call) { switch(data.call) {
case "getCoinBase": case "getCoinBase":
postData(data._seed, eth.getCoinBase()) postData(data._seed, eth.getCoinBase())
break
break
case "getIsListening": case "getIsListening":
postData(data._seed, eth.getIsListening()) postData(data._seed, eth.getIsListening())
break
break
case "getIsMining": case "getIsMining":
postData(data._seed, eth.getIsMining()) postData(data._seed, eth.getIsMining())
break
break
case "getPeerCount": case "getPeerCount":
postData(data._seed, eth.getPeerCount()) postData(data._seed, eth.getPeerCount())
break break
case "getTxCountAt": case "getTxCountAt":
require(1) require(1)
postData(data._seed, eth.getTxCountAt(data.args[0])) postData(data._seed, eth.getTxCountAt(data.args[0]))
break
break
case "getBlockByNumber": case "getBlockByNumber":
var block = eth.getBlock(data.args[0]) var block = eth.getBlock(data.args[0])
postData(data._seed, block) postData(data._seed, block)
break
break
case "getBlockByHash": case "getBlockByHash":
var block = eth.getBlock(data.args[0]) var block = eth.getBlock(data.args[0])
postData(data._seed, block) postData(data._seed, block)
break
break
case "transact": case "transact":
require(5) require(5)
var tx = eth.transact(data.args[0], data.args[1], data.args[2],data.args[3],data.args[4],data.args[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) postData(data._seed, tx)
break break
case "create":
postData(data._seed, null)
break
case "getStorage": case "getStorage":
require(2); require(2);
var stateObject = eth.getStateObject(data.args[0]) var stateObject = eth.getStateObject(data.args[0])
var storage = stateObject.getStorage(data.args[1]) var storage = stateObject.getStorage(data.args[1])
postData(data._seed, storage) postData(data._seed, storage)
break
break
case "getStateKeyVals": case "getStateKeyVals":
require(1); require(1);
var stateObject = eth.getStateObject(data.args[0]).stateKeyVal(true) var stateObject = eth.getStateObject(data.args[0]).stateKeyVal(true)
postData(data._seed,stateObject) postData(data._seed,stateObject)
break
break
case "getTransactionsFor": case "getTransactionsFor":
require(1); require(1);
var txs = eth.getTransactionsFor(data.args[0], true) var txs = eth.getTransactionsFor(data.args[0], true)
postData(data._seed, txs) postData(data._seed, txs)
break
break
case "getBalance": case "getBalance":
require(1); require(1);
postData(data._seed, eth.getStateObject(data.args[0]).value()); postData(data._seed, eth.getStateObject(data.args[0]).value());
break
break
case "getKey": case "getKey":
var key = eth.getKey().privateKey; var key = eth.getKey().privateKey;
postData(data._seed, key)
break
postData(data._seed, key)
break
case "watch": case "watch":
require(1) require(1)
eth.watch(data.args[0], data.args[1]); eth.watch(data.args[0], data.args[1]);
break
break
case "disconnect": case "disconnect":
require(1) require(1)
postData(data._seed, null) postData(data._seed, null)
break;
case "set": break;
console.log("'Set' has been depcrecated")
/*
for(var key in data.args) {
if(webview.hasOwnProperty(key)) {
window[key] = data.args[key];
}
}
*/
break;
case "getSecretToAddress": case "getSecretToAddress":
require(1) require(1)
postData(data._seed, eth.secretToAddress(data.args[0])) postData(data._seed, eth.secretToAddress(data.args[0]))
break;
break;
case "debug": case "debug":
console.log(data.args[0]); console.log(data.args[0]);
break; break;
} }
} catch(e) { } catch(e) {
@ -215,12 +235,13 @@ ApplicationWindow {
postEvent(ev, [storageObject.address, storageObject.value]) postEvent(ev, [storageObject.address, storageObject.value])
} }
} }
Rectangle { Rectangle {
id: toggleInspector id: toggleInspector
color: "#bcbcbc" color: "#bcbcbc"
visible: true visible: true
height: 12 height: 20
width: 12 width: 20
anchors { anchors {
right: root.right right: root.right
} }
@ -233,8 +254,8 @@ ApplicationWindow {
inspector.url = webview.experimental.remoteInspectorUrl inspector.url = webview.experimental.remoteInspectorUrl
} }
} }
onDoubleClicked: { onDoubleClicked: {
console.log('refreshing')
webView.reload() webView.reload()
} }
anchors.fill: parent anchors.fill: parent

View File

@ -282,7 +282,11 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
ptx.Sender = s ptx.Sender = s
ptx.Address = r ptx.Address = r
gui.getObjectByName("transactionView").Call("addTx", window, ptx, inout) if window == "post" {
gui.getObjectByName("transactionView").Call("addTx", ptx, inout)
} else {
gui.getObjectByName("pendingTxView").Call("addTx", ptx, inout)
}
} }
func (gui *Gui) readPreviousTransactions() { func (gui *Gui) readPreviousTransactions() {

View File

@ -17,6 +17,9 @@ const (
func main() { func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
// This is a bit of a cheat, but ey!
os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999")
qml.Init(nil) qml.Init(nil)
var interrupted = false var interrupted = false

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"path" "path"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
@ -42,6 +43,15 @@ func (self *UiLib) EvalJavascriptFile(path string) {
self.jsEngine.LoadExtFile(path[7:]) self.jsEngine.LoadExtFile(path[7:])
} }
func (self *UiLib) EvalJavascriptString(str string) string {
value, err := self.jsEngine.Run(str)
if err != nil {
return err.Error()
}
return fmt.Sprintf("%v", value)
}
func (ui *UiLib) OpenQml(path string) { func (ui *UiLib) OpenQml(path string) {
container := NewQmlApplication(path[7:], ui) container := NewQmlApplication(path[7:], ui)
app := NewExtApplication(container, ui) app := NewExtApplication(container, ui)