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 = {
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
//
// Either supply a number or a string. Type is determent for the lookup method
// string - Retrieves the block by looking up the hash
// number - Retrieves the block by looking up the block number
getBlock: function(numberOrHash, cb) {
var func;
if(typeof numberOrHash == "string") {
func = "getBlockByHash";
} else {
func = "getBlockByNumber";
}
postData({call: func, args: [numberOrHash]}, cb);
},
getBlock: function(numberOrHash, cb) {
var func;
if(typeof numberOrHash == "string") {
func = "getBlockByHash";
} else {
func = "getBlockByNumber";
}
postData({call: func, args: [numberOrHash]}, cb);
},
// Create transaction
//
// Transact between two state objects
transact: function(sec, recipient, value, gas, gasPrice, data, cb) {
postData({call: "transact", args: [sec, recipient, value, gas, gasPrice, data]}, cb);
},
transact: function(params, cb) {
if(params === undefined) {
params = {};
}
create: function(sec, value, gas, gasPrice, init, body, cb) {
postData({call: "create", args: [sec, value, gas, gasPrice, init, body]}, cb);
if(params.endowment !== undefined)
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) {

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
}
function addTx(type, tx, inout) {
function addTx(tx, inout) {
var isContract
if (tx.contract == true){
isContract = "Yes"

View File

@ -17,6 +17,7 @@ Rectangle {
color: "#00000000"
Column {
id: info
spacing: 3
anchors.fill: parent
anchors.topMargin: 5
@ -49,7 +50,7 @@ Rectangle {
}
TableView {
id: addressView
width: parent.width - 200
width: parent.width
height: 200
anchors.bottom: logLayout.top
TableViewColumn{ role: "name"; title: "name" }
@ -58,30 +59,6 @@ Rectangle {
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 {
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
}
function addTx(type, tx, inout) {
function addTx(tx, inout) {
var isContract
if (tx.contract == true){
isContract = "Yes"

View File

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

View File

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

View File

@ -282,7 +282,11 @@ func (gui *Gui) insertTransaction(window string, tx *ethchain.Transaction) {
ptx.Sender = s
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() {

View File

@ -17,6 +17,9 @@ const (
func main() {
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)
var interrupted = false

View File

@ -1,6 +1,7 @@
package main
import (
"fmt"
"path"
"github.com/ethereum/eth-go"
@ -42,6 +43,15 @@ func (self *UiLib) EvalJavascriptFile(path string) {
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) {
container := NewQmlApplication(path[7:], ui)
app := NewExtApplication(container, ui)