Re-wrote ethereum.js

pull/136/head
obscuren 10 years ago
parent 8585e59718
commit b4bd70c402
  1. 8
      mist/assets/debugger/debugger.qml
  2. 8
      mist/assets/ext/filter.js
  3. 350
      mist/assets/ext/html_messaging.js
  4. 38
      mist/assets/ext/pre.js
  5. 12
      mist/assets/qml/wallet.qml
  6. 570
      mist/assets/qml/webapp.qml
  7. 2
      mist/debugger.go
  8. 44
      mist/ui_lib.go

@ -221,7 +221,7 @@ ApplicationWindow {
}
height: parent.height
width: 300
TableViewColumn{ role: "value" ; title: "Temp" ; width: 200 }
TableViewColumn{ role: "value" ; title: "Local VM stack" ; width: stackTableView.width - 2 }
model: stackModel
}
@ -233,7 +233,7 @@ ApplicationWindow {
height: parent.height
width: parent.width - stackTableView.width
TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50 }
TableViewColumn{ role: "value" ; title: "Memory" ; width: 750 }
TableViewColumn{ role: "value" ; title: "Memory" ; width: 650 }
model: memModel
}
}
@ -248,8 +248,8 @@ ApplicationWindow {
}
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}
TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2 - 1}
TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2 - 1}
model: storageModel
}
}

@ -31,11 +31,11 @@ Filter.prototype.changed = function(callback) {
this.callbacks.push(callback);
var self = this;
message.connect(function(messages, id) {
messages.connect(function(messages, id) {
if(id == self.id) {
for(var i = 0; i < self.callbacks.length; i++) {
self.callbacks[i].call(self, messages);
}
for(var i = 0; i < self.callbacks.length; i++) {
self.callbacks[i].call(self, messages);
}
}
});
};

@ -12,15 +12,46 @@
window.eth = {
_callbacks: {},
_onCallbacks: {},
_events: {},
prototype: Object(),
coinbase: function() {
return new Promise(function(resolve, reject) {
postData({call: "getCoinBase"}, function(coinbase) {
resolve(coinbase);
});
});
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) {
@ -107,17 +138,316 @@
});
},
key: function() {
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 = Math.floor(Math.random() * 1000000)
data._seed = g_seed;
if(cb) {
eth._callbacks[data._seed] = cb;
}
@ -126,6 +456,8 @@
data.args = [];
}
g_seed++;
navigator.qt.postMessage(JSON.stringify(data));
}

@ -1,41 +1,3 @@
// 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];
}
}
}
}
if(typeof(Promise) === "undefined") {
window.Promise = Q.Promise;
}

@ -14,20 +14,22 @@ ApplicationWindow {
property alias miningButtonText: miningButton.text
property var ethx : Eth.ethx
property var web
width: 900
height: 600
width: 1024
height: 750
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 message(var callback, int seed);
signal messages(var messages, int id);
function invokeFilterCallback(data, receiverSeed) {
//var messages = JSON.parse(data)
// Signal handler
message(data, receiverSeed);
messages(data, receiverSeed);
root.web.messages(data, receiverSeed);
}
TextField {
@ -44,7 +46,7 @@ ApplicationWindow {
// Takes care of loading all default plugins
Component.onCompleted: {
addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true});
root.web = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true});
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});

@ -10,265 +10,279 @@ 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
Rectangle {
id: window
property var title: "Browser"
property var iconSource: "../browser.png"
property var menuItem
property alias url: webview.url
property alias webView: webview
property alias url: webview.url
property alias webView: webview
Component.onCompleted: {
webview.url = "http://etherian.io"
}
Component.onCompleted: {
webview.url = "http://etherian.io"
}
Item {
objectName: "root"
id: root
anchors.fill: parent
state: "inspectorShown"
RowLayout {
id: navBar
height: 40
anchors {
left: parent.left
right: parent.right
leftMargin: 7
}
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]);
}
Button {
id: back
onClicked: {
webview.goBack()
}
style: ButtonStyle {
background: Image {
source: "../back.png"
width: 30
height: 30
}
}
}
Item {
objectName: "root"
id: root
anchors.fill: parent
state: "inspectorShown"
TextField {
RowLayout {
id: navBar
height: 40
anchors {
left: back.right
right: toggleInspector.left
leftMargin: 5
rightMargin: 5
left: parent.left
right: parent.right
leftMargin: 7
}
text: "http://etherian.io"
id: uriNav
y: parent.height / 2 - this.height / 2
Keys.onReturnPressed: {
webview.url = this.text;
Button {
id: back
onClicked: {
webview.goBack()
}
style: ButtonStyle {
background: Image {
source: "../back.png"
width: 30
height: 30
}
}
}
}
Button {
id: toggleInspector
anchors {
right: parent.right
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;
}
}
iconSource: "../bug.png"
onClicked: {
if(inspector.visible == true){
inspector.visible = false
}else{
inspector.visible = true
inspector.url = webview.experimental.remoteInspectorUrl
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
}
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;
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;
}
}
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;
}
function sendMessage(data) {
webview.experimental.postMessage(JSON.stringify(data))
}
uri += path;
});
onTitleChanged: {
var data = Messaging.HandleMessage(title);
if(data) {
sendMessage(data)
}
this.cleanPath = true;
webview.url = uri;
} else {
// Prevent inf loop.
this.cleanPath = false;
}
}
function sendMessage(data) {
//this.experimental.evaluateJavaScript("window.____returnData="+JSON.stringify(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
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)
case "getCoinBase":
postData(data._seed, eth.coinBase())
try {
switch(data.call) {
case "compile":
postData(data._seed, eth.compile(data.args[0]))
break
break
case "getCoinBase":
postData(data._seed, eth.coinBase())
case "getIsListening":
postData(data._seed, eth.isListening())
break
break
case "getIsListening":
postData(data._seed, eth.isListening())
case "getIsMining":
postData(data._seed, eth.isMining())
break
break
case "getIsMining":
postData(data._seed, eth.isMining())
case "getPeerCount":
postData(data._seed, eth.peerCount())
break
break
case "getPeerCount":
postData(data._seed, eth.peerCount())
case "getCountAt":
require(1)
postData(data._seed, eth.txCountAt(data.args[0]))
break
break
case "getTxCountAt":
require(1)
postData(data._seed, eth.txCountAt(data.args[0]))
case "getCodeAt":
require(1)
var code = eth.codeAt(data.args[0])
postData(data._seed, code);
break
break
case "getBlockByNumber":
var block = eth.blockByNumber(data.args[0])
postData(data._seed, block)
case "getBlockByNumber":
var block = eth.blockByNumber(data.args[0])
postData(data._seed, block)
break
break
case "getBlockByHash":
var block = eth.blockByHash(data.args[0])
postData(data._seed, block)
case "getBlockByHash":
var block = eth.blockByHash(data.args[0])
postData(data._seed, block)
break
break
case "transact":
require(5)
case "transact":
require(5)
var tx = eth.transact(data.args)
console.log("transactx", tx)
postData(data._seed, tx)
var tx = eth.transact(data.args)
postData(data._seed, tx)
break
break
case "getStorage":
require(2);
case "getStorageAt":
require(2);
var stateObject = eth.stateObject(data.args[0])
var storage = stateObject.storageAt(data.args[1])
postData(data._seed, storage)
var storage = eth.storageAt(data.args[0], data.args[1]);
postData(data._seed, storage)
break
break
case "getEachStorage":
require(1);
var storage = JSON.parse(eth.eachStorage(data.args[0]))
postData(data._seed, storage)
case "call":
require(1);
var ret = eth.call(data.args)
postData(data._seed, ret)
break
break
case "getTransactionsFor":
require(1);
var txs = eth.transactionsFor(data.args[0], true)
postData(data._seed, txs)
case "getEachStorage":
require(1);
var storage = JSON.parse(eth.eachStorage(data.args[0]))
postData(data._seed, storage)
break
break
case "getBalance":
require(1);
case "getTransactionsFor":
require(1);
var txs = eth.transactionsFor(data.args[0], true)
postData(data._seed, txs)
postData(data._seed, eth.stateObject(data.args[0]).value());
break
break
case "getBalanceAt":
require(1);
case "getKey":
var key = eth.key().privateKey;
postData(data._seed, eth.balanceAt(data.args[0]));
postData(data._seed, key)
break
break
/*
case "watch":
require(1)
eth.watch(data.args[0], data.args[1]);
case "getKey":
var key = eth.key().privateKey;
postData(data._seed, key)
break
*/
case "watch":
require(2)
case "watch":
require(2)
eth.watch(data.args[0], data.args[1])
case "disconnect":
require(1)
postData(data._seed, null)
case "disconnect":
require(1)
postData(data._seed, null)
break;
break;
case "getSecretToAddress":
require(1)
case "getSecretToAddress":
require(1)
postData(data._seed, eth.secretToAddress(data.args[0]))
var addr = eth.secretToAddress(data.args[0])
console.log("getsecret", addr)
postData(data._seed, addr)
break;
break;
case "messages":
case "messages":
require(1);
var messages = JSON.parse(eth.getMessages(data.args[0]))
@ -276,94 +290,120 @@ Rectangle {
break
case "mutan":
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);
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) {
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 post(seed, data) {
postData(data._seed, data)
}
}
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 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 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])
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
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
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
states: [
State {
name: "inspectorShown"
PropertyChanges {
target: inspector
}
}
}
]
]
}
}
}

@ -276,7 +276,7 @@ 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 += 16 {
for i := 0; i+16 <= mem.Len(); i += 16 {
dat := mem.Data()[i : i+16]
var str string

@ -37,7 +37,6 @@ type UiLib struct {
jsEngine *javascript.JSRE
filterCallbacks map[int][]int
//filters map[int]*ethpipe.JSFilter
}
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
@ -201,7 +200,7 @@ 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"] = ""
@ -223,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 {
@ -238,14 +239,29 @@ 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"],
)
}
@ -257,3 +273,15 @@ func (self *UiLib) Compile(code string) (string, error) {
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"],
)
}

Loading…
Cancel
Save