From 44db1a1eb20275349985f1f1b5eddd9a28731488 Mon Sep 17 00:00:00 2001 From: Maran Date: Wed, 28 May 2014 18:11:27 +0200 Subject: [PATCH 1/2] Add 0x when feeding data to debugger --- ethereal/ui/ui_lib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereal/ui/ui_lib.go b/ethereal/ui/ui_lib.go index 9c4301ffe4..9f2cca1e01 100644 --- a/ethereal/ui/ui_lib.go +++ b/ethereal/ui/ui_lib.go @@ -95,7 +95,7 @@ func (self *UiLib) StartDbWithContractAndData(contractHash, data string) { if len(object.Script()) > 0 { dbWindow.SetCode("0x" + ethutil.Hex(object.Script())) } - dbWindow.SetData(data) + dbWindow.SetData("0x" + data) dbWindow.Show() } From 8fab7ce37d6748cbf34ebee96622448ec8a4c9e3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 28 May 2014 23:14:23 +0200 Subject: [PATCH 2/2] Fixes and improved debugger --- ethereal/assets/debugger/debugger.qml | 394 ++-- ethereal/assets/qml/wallet.qml | 2002 ++++++++++---------- ethereal/assets/samplecoin/samplecoin.html | 2 +- ethereal/ui/debugger.go | 46 +- ethereal/ui/gui.go | 2 +- 5 files changed, 1228 insertions(+), 1218 deletions(-) diff --git a/ethereal/assets/debugger/debugger.qml b/ethereal/assets/debugger/debugger.qml index 40b0b68b1d..bff653fb80 100644 --- a/ethereal/assets/debugger/debugger.qml +++ b/ethereal/assets/debugger/debugger.qml @@ -7,12 +7,12 @@ import QtQuick.Controls.Styles 1.1 import Ethereum 1.0 ApplicationWindow { - visible: false - title: "IceCream" - minimumWidth: 1280 - minimumHeight: 900 - width: 1290 - height: 900 + visible: false + title: "IceCream" + minimumWidth: 1280 + minimumHeight: 900 + width: 1290 + height: 900 property alias codeText: codeEditor.text property alias dataText: rawDataField.text @@ -32,209 +32,229 @@ ApplicationWindow { onTriggered: dbg.next() } } - } + } - SplitView { - anchors.fill: parent - property var asmModel: ListModel { - id: asmModel - } - TableView { - id: asmTableView - width: 200 - TableViewColumn{ role: "value" ; title: "" ; width: 100 } - model: asmModel - } + SplitView { + anchors.fill: parent + property var asmModel: ListModel { + id: asmModel + } + TableView { + id: asmTableView + width: 200 + TableViewColumn{ role: "value" ; title: "" ; width: 100 } + model: asmModel + } - Rectangle { - color: "#00000000" - anchors.left: asmTableView.right - anchors.right: parent.right - SplitView { - orientation: Qt.Vertical - anchors.fill: parent + Rectangle { + color: "#00000000" + anchors.left: asmTableView.right + anchors.right: parent.right + SplitView { + orientation: Qt.Vertical + anchors.fill: parent - Rectangle { - color: "#00000000" - height: 500 - anchors.left: parent.left - anchors.right: parent.right + Rectangle { + color: "#00000000" + height: 500 + anchors.left: parent.left + anchors.right: parent.right - TextArea { - id: codeEditor - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: settings.left - } + TextArea { + id: codeEditor + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: settings.left + } - Column { - id: settings - spacing: 5 - width: 300 - height: parent.height - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom + Column { + id: settings + spacing: 5 + width: 300 + height: parent.height + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom - Label { - text: "Arbitrary data" - } - TextArea { - id: rawDataField - anchors.left: parent.left - anchors.right: parent.right - height: 150 - } + Label { + text: "Arbitrary data" + } + TextArea { + id: rawDataField + anchors.left: parent.left + anchors.right: parent.right + height: 150 + } - Label { - text: "Amount" - } - TextField { - id: txValue - width: 200 - placeholderText: "Amount" - validator: RegExpValidator { regExp: /\d*/ } - } - Label { - text: "Amount of gas" - } - TextField { - id: txGas - width: 200 - validator: RegExpValidator { regExp: /\d*/ } - text: "10000" - placeholderText: "Gas" - } - Label { - text: "Gas price" - } - TextField { - id: txGasPrice - width: 200 - placeholderText: "Gas price" - text: "1000000000000" - validator: RegExpValidator { regExp: /\d*/ } - } - } - } + Label { + text: "Amount" + } + TextField { + id: txValue + width: 200 + placeholderText: "Amount" + validator: RegExpValidator { regExp: /\d*/ } + } + Label { + text: "Amount of gas" + } + TextField { + id: txGas + width: 200 + validator: RegExpValidator { regExp: /\d*/ } + text: "10000" + placeholderText: "Gas" + } + Label { + text: "Gas price" + } + TextField { + id: txGasPrice + width: 200 + placeholderText: "Gas price" + text: "1000000000000" + validator: RegExpValidator { regExp: /\d*/ } + } + } + } - SplitView { - orientation: Qt.Vertical - id: inspectorPane - height: 500 + SplitView { + orientation: Qt.Vertical + id: inspectorPane + height: 500 - SplitView { - orientation: Qt.Horizontal - height: 250 + SplitView { + orientation: Qt.Horizontal + height: 150 - TableView { - id: stackTableView - property var stackModel: ListModel { - id: stackModel - } - height: parent.height - width: 300 - TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 } - model: stackModel - } + TableView { + id: stackTableView + property var stackModel: ListModel { + id: stackModel + } + height: parent.height + width: 300 + TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 } + model: stackModel + } - TableView { - id: memoryTableView - property var memModel: ListModel { - id: memModel - } - height: parent.height - width: parent.width - stackTableView.width - TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} - TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} - model: memModel - } - } + TableView { + id: memoryTableView + property var memModel: ListModel { + id: memModel + } + height: parent.height + width: parent.width - stackTableView.width + TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} + TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} + model: memModel + } + } - SplitView { - height: 300 - TableView { - id: storageTableView - property var memModel: ListModel { - id: storageModel - } - height: parent.height - width: parent.width - stackTableView.width - TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2} - TableViewColumn{ role: "value" ; title: "value" ; width: storageTableView.width / 2} - model: storageModel - } - } - } - } - } - } + Rectangle { + height: 100 + width: parent.width + TableView { + id: storageTableView + property var memModel: ListModel { + id: storageModel + } + height: parent.height + width: parent.width + TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2} + TableViewColumn{ role: "value" ; title: "value" ; width: storageTableView.width / 2} + model: storageModel + } + } - toolBar: ToolBar { - RowLayout { - spacing: 5 + Rectangle { + height: 200 + width: parent.width + TableView { + id: logTableView + property var logModel: ListModel { + id: logModel + } + height: parent.height + width: parent.width + TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width } + model: logModel + } + } + } + } + } + } - Button { - property var enabled: true - id: debugStart - onClicked: { - debugCurrent() - } - text: "Debug" - } + toolBar: ToolBar { + RowLayout { + spacing: 5 - Button { - property var enabled: true - id: debugNextButton - onClicked: { - dbg.next() - } - text: "Next" - } - } - } + Button { + property var enabled: true + id: debugStart + onClicked: { + debugCurrent() + } + text: "Debug" + } - function debugCurrent() { - dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text) - } + Button { + property var enabled: true + id: debugNextButton + onClicked: { + dbg.next() + } + text: "Next" + } + } + } - function setAsm(asm) { - asmModel.append({asm: asm}) - } + function debugCurrent() { + dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text) + } - function clearAsm() { - asmModel.clear() - } + function setAsm(asm) { + asmModel.append({asm: asm}) + } - function setInstruction(num) { - asmTableView.selection.clear() - asmTableView.selection.select(num) - } + function clearAsm() { + asmModel.clear() + } - function setMem(mem) { - memModel.append({num: mem.num, value: mem.value}) - } - function clearMem(){ - memModel.clear() - } + function setInstruction(num) { + asmTableView.selection.clear() + asmTableView.selection.select(num) + } - function setStack(stack) { - stackModel.append({value: stack}) - } - function addDebugMessage(message){ - debuggerLog.append({value: message}) - } + function setMem(mem) { + memModel.append({num: mem.num, value: mem.value}) + } + function clearMem(){ + memModel.clear() + } - function clearStack() { - stackModel.clear() - } + function setStack(stack) { + stackModel.append({value: stack}) + } + function addDebugMessage(message){ + debuggerLog.append({value: message}) + } - function clearStorage() { - storageModel.clear() - } + function clearStack() { + stackModel.clear() + } - function setStorage(storage) { - storageModel.append({key: storage.key, value: storage.value}) - } + function clearStorage() { + storageModel.clear() + } + + function setStorage(storage) { + storageModel.append({key: storage.key, value: storage.value}) + } + + function setLog(msg) { + logModel.append({message: msg}) + } } diff --git a/ethereal/assets/qml/wallet.qml b/ethereal/assets/qml/wallet.qml index 82b6809132..ce8ba5745f 100644 --- a/ethereal/assets/qml/wallet.qml +++ b/ethereal/assets/qml/wallet.qml @@ -8,1006 +8,1006 @@ import Ethereum 1.0 ApplicationWindow { - id: root - - width: 900 - height: 600 - minimumHeight: 300 - - title: "Ethereal" - - MenuBar { - Menu { - title: "File" - MenuItem { - text: "Import App" - shortcut: "Ctrl+o" - onTriggered: openAppDialog.open() - } - } - - Menu { - title: "Tools" - MenuItem { - text: "Muted" - shortcut: "Ctrl+e" - onTriggered: ui.muted("") - } - - MenuItem { - text: "Debugger" - shortcut: "Ctrl+d" - onTriggered: ui.startDebugger() - } - } - - Menu { - title: "Network" - MenuItem { - text: "Add Peer" - shortcut: "Ctrl+p" - onTriggered: { - addPeerWin.visible = true - } - } - - MenuItem { - text: "Start" - onTriggered: ui.connect() - } - } - - Menu { - title: "Help" - MenuItem { - text: "About" - onTriggered: { - aboutWin.visible = true - } - } - } - - } - - - property var blockModel: ListModel { - id: blockModel - } - - function setView(view) { - networkView.visible = false - historyView.visible = false - newTxView.visible = false - infoView.visible = false - view.visible = true - //root.title = "Ethereal - " = view.title - } - - SplitView { - anchors.fill: parent - resizing: false - - Rectangle { - id: menu - Layout.minimumWidth: 80 - Layout.maximumWidth: 80 - anchors.bottom: parent.bottom - anchors.top: parent.top - //color: "#D9DDE7" - color: "#252525" - - ColumnLayout { - y: 50 - anchors.left: parent.left - anchors.right: parent.right - height: 200 - Image { - source: ui.assetPath("tx.png") - anchors.horizontalCenter: parent.horizontalCenter - MouseArea { - anchors.fill: parent - onClicked: { - setView(historyView) - } - } - } - Image { - source: ui.assetPath("new.png") - anchors.horizontalCenter: parent.horizontalCenter - MouseArea { - anchors.fill: parent - onClicked: { - setView(newTxView) - } - } - } - Image { - source: ui.assetPath("net.png") - anchors.horizontalCenter: parent.horizontalCenter - MouseArea { - anchors.fill: parent - onClicked: { - setView(networkView) - } - } - } - - Image { - source: ui.assetPath("heart.png") - anchors.horizontalCenter: parent.horizontalCenter - MouseArea { - anchors.fill: parent - onClicked: { - setView(infoView) - } - } - } - } - } - - Rectangle { - id: mainView - color: "#00000000" - anchors.right: parent.right - anchors.left: menu.right - anchors.bottom: parent.bottom - anchors.top: parent.top - - property var txModel: ListModel { - id: txModel - } - - Rectangle { - id: historyView - anchors.fill: parent - - property var title: "Transactions" - TableView { - id: txTableView - anchors.fill: parent - TableViewColumn{ role: "inout" ; title: "" ; width: 40 } - TableViewColumn{ role: "value" ; title: "Value" ; width: 100 } - TableViewColumn{ role: "address" ; title: "Address" ; width: 430 } - TableViewColumn{ role: "contract" ; title: "Contract" ; width: 100 } - - model: txModel - } - } - - Rectangle { - id: newTxView - property var title: "New transaction" - visible: false - anchors.fill: parent - color: "#00000000" - TabView{ - anchors.fill: parent - anchors.rightMargin: 5 - anchors.leftMargin: 5 - anchors.topMargin: 5 - anchors.bottomMargin: 5 - id: newTransactionTab - Component.onCompleted:{ - addTab("Simple send", newTransaction) - addTab("Contracts", newContract) - } - } - } - - Rectangle { - id: networkView - property var title: "Network" - visible: false - anchors.fill: parent - - TableView { - id: blockTable - width: parent.width - anchors.top: parent.top - anchors.bottom: logView.top - TableViewColumn{ role: "number" ; title: "#" ; width: 100 } - TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } - TableViewColumn{ role: "txAmount" ; title: "Tx amount" ; width: 100 } - - model: blockModel - - onDoubleClicked: { - popup.visible = true - popup.setDetails(blockModel.get(row)) - } - } - - property var logModel: ListModel { - id: logModel - } - - TableView { - id: logView - width: parent.width - height: 150 - anchors.bottom: parent.bottom - TableViewColumn{ role: "description" ; title: "log" } - - model: logModel - } - } - - Rectangle { - id: infoView - property var title: "Information" - visible: false - color: "#00000000" - anchors.fill: parent - - Label { - id: addressLabel - text: "Address" - anchors { - margins: 5 - top: parent.top - left: parent.left - } - } - TextField { - anchors { - margins: 5 - left: addressLabel.right - top: parent.top - } - text: pub.getKey().address - width: 500 - } - } - - /* - signal addPlugin(string name) - Component { - id: pluginWindow - Rectangle { - anchors.fill: parent - Label { - id: pluginTitle - anchors.centerIn: parent - text: "Hello world" - } - Component.onCompleted: setView(this) - } - } - - onAddPlugin: { - var pluginWin = pluginWindow.createObject(mainView) - console.log(pluginWin) - pluginWin.pluginTitle.text = "Test" - } - */ - } - } - - FileDialog { - id: openAppDialog - title: "Open QML Application" - onAccepted: { - //ui.open(openAppDialog.fileUrl.toString()) - //ui.openHtml(Qt.resolvedUrl(ui.assetPath("test.html"))) - ui.openHtml(openAppDialog.fileUrl.toString()) - } - } - - statusBar: StatusBar { - RowLayout { - anchors.fill: parent - - Button { - property var enabled: true - id: debuggerWindow - onClicked: { - ui.startDebugger() - } - text: "Debugger" - } - - Button { - id: importAppButton - anchors.left: debuggerWindow.right - anchors.leftMargin: 5 - onClicked: openAppDialog.open() - text: "Import App" - } - - Label { - anchors.left: importAppButton.right - anchors.leftMargin: 5 - id: walletValueLabel - } - - Label { - anchors.right: peerImage.left - anchors.rightMargin: 5 - id: peerLabel - font.pixelSize: 8 - text: "0 / 0" - } - Image { - id: peerImage - anchors.right: parent.right - width: 10; height: 10 - source: ui.assetPath("network.png") - } - } - } - - Window { - id: popup - visible: false - property var block - width: root.width - height: 240 - x: root.x - y: root.y + root.height - Component{ - id: blockDetailsDelegate - Rectangle { - color: "#252525" - width: popup.width - height: 200 - Column { - anchors.leftMargin: 10 - anchors.topMargin: 5 - anchors.top: parent.top - anchors.left: parent.left - Text { text: '

Block details

'; color: "#F2F2F2"} - Text { text: 'Block number: ' + number; color: "#F2F2F2"} - Text { text: 'Hash: ' + hash; color: "#F2F2F2"} - Text { text: 'Block found at: ' + prettyTime; color: "#F2F2F2"} - } - } - } - ListView { - model: singleBlock - delegate: blockDetailsDelegate - anchors.top: parent.top - height: 70 - anchors.leftMargin: 20 - id: listViewThing - Layout.maximumHeight: 40 - } - TableView { - id: txView - anchors.top: listViewThing.bottom - anchors.topMargin: 50 - width: parent.width - - TableViewColumn{width: 90; role: "value" ; title: "Value" } - TableViewColumn{width: 200; role: "hash" ; title: "Hash" } - TableViewColumn{width: 200; role: "sender" ; title: "Sender" } - TableViewColumn{width: 200;role: "address" ; title: "Receiver" } - TableViewColumn{width: 60; role: "gas" ; title: "Gas" } - TableViewColumn{width: 60; role: "gasPrice" ; title: "Gas Price" } - TableViewColumn{width: 60; role: "isContract" ; title: "Contract" } - - model: transactionModel - onClicked: { - var tx = transactionModel.get(row) - if(tx.data) { - popup.showContractData(tx) - }else{ - popup.height = 230 - } - } - } - - function showContractData(tx) { - txDetailsDebugButton.tx = tx - if(tx.createsContract) { - contractData.text = tx.data - contractLabel.text = "

Transaction created contract " + tx.address + "

" - }else{ - contractLabel.text = "

Transaction ran contract " + tx.address + "

" - contractData.text = tx.rawData - } - popup.height = 400 - } - - Rectangle { - id: txDetails - width: popup.width - height: 300 - anchors.left: listViewThing.left - anchors.top: txView.bottom - Label { - text: "

Contract data

" - anchors.top: parent.top - anchors.left: parent.left - id: contractLabel - anchors.leftMargin: 10 - } - Button { - property var tx - id: txDetailsDebugButton - anchors.right: parent.right - anchors.rightMargin: 10 - anchors.top: parent.top - anchors.topMargin: 10 - text: "Debug contract" - onClicked: { - if(tx.createsContract){ - ui.startDbWithCode(tx.rawData) - }else { - ui.startDbWithContractAndData(tx.address, tx.rawData) - } - } - } - TextArea { - id: contractData - text: "Contract" - anchors.top: contractLabel.bottom - anchors.left: parent.left - wrapMode: Text.Wrap - width: parent.width - 30 - height: 80 - anchors.leftMargin: 10 - } - } - property var transactionModel: ListModel { - id: transactionModel - } - property var singleBlock: ListModel { - id: singleBlock - } - function setDetails(block){ - singleBlock.set(0,block) - popup.height = 230 - transactionModel.clear() - if(block.txs != undefined){ - for(var i = 0; i < block.txs.count; ++i) { - transactionModel.insert(0, block.txs.get(i)) - } - if(block.txs.get(0).data){ - popup.showContractData(block.txs.get(0)) - } - } - txView.forceActiveFocus() - } - } - - Window { - id: addPeerWin - visible: false - minimumWidth: 230 - maximumWidth: 230 - maximumHeight: 50 - minimumHeight: 50 - - TextField { - id: addrField - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 10 - placeholderText: "address:port" - onAccepted: { - ui.connectToPeer(addrField.text) - addPeerWin.visible = false - } - } - Button { - anchors.left: addrField.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: 5 - text: "Add" - onClicked: { - ui.connectToPeer(addrField.text) - addPeerWin.visible = false - } - } - Component.onCompleted: { - addrField.focus = true - } - } - - Window { - id: aboutWin - visible: false - title: "About" - minimumWidth: 350 - maximumWidth: 350 - maximumHeight: 200 - minimumHeight: 200 - - Image { - id: aboutIcon - height: 150 - width: 150 - fillMode: Image.PreserveAspectFit - smooth: true - source: ui.assetPath("facet.png") - x: 10 - y: 10 - } - - Text { - anchors.left: aboutIcon.right - anchors.leftMargin: 10 - font.pointSize: 12 - text: "

Ethereal


Development

Jeffrey Wilcke
Maran Hidskes
" - } - - } - - ApplicationWindow { - id: debugWindow - visible: false - title: "Debugger" - minimumWidth: 600 - minimumHeight: 600 - width: 800 - height: 600 - - - Item { - id: keyHandler - focus: true - Keys.onPressed: { - if (event.key == Qt.Key_Space) { - ui.next() - } - } - } - SplitView { - anchors.fill: parent - property var asmModel: ListModel { - id: asmModel - } - TableView { - id: asmTableView - width: 200 - TableViewColumn{ role: "value" ; title: "" ; width: 100 } - model: asmModel - } - - Rectangle { - anchors.left: asmTableView.right - anchors.right: parent.right - SplitView { - orientation: Qt.Vertical - anchors.fill: parent - - TableView { - property var memModel: ListModel { - id: memModel - } - height: parent.height/2 - width: parent.width - TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} - TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} - model: memModel - } - - SplitView { - orientation: Qt.Horizontal - id: debugSplitView - TableView { - property var debuggerLog: ListModel { - id: debuggerLog - } - TableViewColumn{ role: "value"; title: "Debug messages" } - model: debuggerLog - } - TableView { - property var stackModel: ListModel { - id: stackModel - } - height: parent.height/2 - width: parent.width - TableViewColumn{ role: "value" ; title: "Stack" ; width: debugSplitView.width } - model: stackModel - } - } - } - } - } - statusBar: StatusBar { - RowLayout { - anchors.fill: parent - Button { - property var enabled: true - id: debugNextButton - onClicked: { - ui.next() - } - text: "Next" - } - } - } - } - - function setAsm(asm) { - asmModel.append({asm: asm}) - } - - function setInstruction(num) { - asmTableView.selection.clear() - asmTableView.selection.select(num-1) - } - - function clearAsm() { - asmModel.clear() - } - - function setMem(mem) { - memModel.append({num: mem.num, value: mem.value}) - } - function clearMem(){ - memModel.clear() - } - - function setStack(stack) { - stackModel.append({value: stack}) - } - function addDebugMessage(message){ - console.log("WOOP:") - debuggerLog.append({value: message}) - } - - function clearStack() { - stackModel.clear() - } - - function loadPlugin(name) { - console.log("Loading plugin" + name) - mainView.addPlugin(name) - } - - function setWalletValue(value) { - walletValueLabel.text = value - } - - function addTx(tx, inout) { - var isContract - if (tx.contract == true){ - isContract = "Yes" - }else{ - isContract = "No" - } - txModel.insert(0, {inout: inout, hash: tx.hash, address: tx.address, value: tx.value, contract: isContract}) - } - - function addBlock(block, initial) { - var txs = JSON.parse(block.transactions); - var amount = 0 - if(initial == undefined){ - initial = false - } - - if(txs != null){ - amount = txs.length - } - - if(initial){ - blockModel.append({number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) - }else{ - blockModel.insert(0, {number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) - } - } - - function addLog(str) { - if(str.len != 0) { - logModel.append({description: str}) - } - } - - function setPeers(text) { - peerLabel.text = text - } - function convertToPretty(unixTs){ - var a = new Date(unixTs*1000); - var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; - var year = a.getFullYear(); - var month = months[a.getMonth()]; - var date = a.getDate(); - var hour = a.getHours(); - var min = a.getMinutes(); - var sec = a.getSeconds(); - var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; - return time; - } - // ******************************************* - // Components - // ******************************************* - - // New Contract component - Component { - id: newContract - Column { - id: mainContractColumn - function contractFormReady(){ - if(codeView.text.length > 0 && txValue.text.length > 0 && txGas.text.length > 0 && txGasPrice.length > 0) { - txButton.state = "READY" - }else{ - txButton.state = "NOTREADY" - } - } - states: [ - State{ - name: "ERROR" - PropertyChanges { target: txResult; visible:true} - PropertyChanges { target: codeView; visible:true} - }, - State { - name: "DONE" - PropertyChanges { target: txValue; visible:false} - PropertyChanges { target: txGas; visible:false} - PropertyChanges { target: txGasPrice; visible:false} - PropertyChanges { target: codeView; visible:false} - PropertyChanges { target: txButton; visible:false} - PropertyChanges { target: txDataLabel; visible:false} - - PropertyChanges { target: txResult; visible:true} - PropertyChanges { target: txOutput; visible:true} - PropertyChanges { target: newTxButton; visible:true} - }, - State { - name: "SETUP" - PropertyChanges { target: txValue; visible:true; text: ""} - PropertyChanges { target: txGas; visible:true; text: ""} - PropertyChanges { target: txGasPrice; visible:true; text: ""} - PropertyChanges { target: codeView; visible:true; text: ""} - PropertyChanges { target: txButton; visible:true} - PropertyChanges { target: txDataLabel; visible:true} - - PropertyChanges { target: txResult; visible:false} - PropertyChanges { target: txOutput; visible:false} - PropertyChanges { target: newTxButton; visible:false} - } - ] - width: 400 - spacing: 5 - anchors.left: parent.left - anchors.top: parent.top - anchors.leftMargin: 5 - anchors.topMargin: 5 - - TextField { - id: txValue - width: 200 - placeholderText: "Amount" - validator: RegExpValidator { regExp: /\d*/ } - onTextChanged: { - contractFormReady() - } - } - TextField { - id: txGas - width: 200 - validator: RegExpValidator { regExp: /\d*/ } - placeholderText: "Gas" - onTextChanged: { - contractFormReady() - } - } - TextField { - id: txGasPrice - width: 200 - placeholderText: "Gas price" - validator: RegExpValidator { regExp: /\d*/ } - onTextChanged: { - contractFormReady() - } - } - - Row { - id: rowContract - ExclusiveGroup { id: contractTypeGroup } - RadioButton { - id: createContractRadio - text: "Create contract" - checked: true - exclusiveGroup: contractTypeGroup - onClicked: { - txFuelRecipient.visible = false - txDataLabel.text = "Contract code" - } - } - RadioButton { - id: runContractRadio - text: "Run contract" - exclusiveGroup: contractTypeGroup - onClicked: { - txFuelRecipient.visible = true - txDataLabel.text = "Contract arguments" - } - } - } - - - Label { - id: txDataLabel - text: "Contract code" - } - - TextArea { - id: codeView - height: 300 - anchors.topMargin: 5 - Layout.fillWidth: true - width: parent.width /2 - onTextChanged: { - contractFormReady() - } - } - - TextField { - id: txFuelRecipient - placeholderText: "Contract address" - validator: RegExpValidator { regExp: /[a-f0-9]{40}/ } - visible: false - width: 530 - } - - Button { - id: txButton - /* enabled: false */ - states: [ - State { - name: "READY" - PropertyChanges { target: txButton; /*enabled: true*/} - }, - State { - name: "NOTREADY" - PropertyChanges { target: txButton; /*enabled:false*/} - } - ] - text: "Send" - onClicked: { - //this.enabled = false - var res = eth.create(txFuelRecipient.text, txValue.text, txGas.text, txGasPrice.text, codeView.text) - if(res[1]) { - txResult.text = "Your contract could not be send over the network:\n" - txResult.text += res[1].error() - txResult.text += "" - mainContractColumn.state = "ERROR" - } else { - txResult.text = "Your transaction has been submitted:\n" - txOutput.text = res[0].address - mainContractColumn.state = "DONE" - } - } - } - Text { - id: txResult - visible: false - } - TextField { - id: txOutput - visible: false - width: 530 - } - Button { - id: newTxButton - visible: false - text: "Create an other contract" - onClicked: { - this.visible = false - txResult.text = "" - txOutput.text = "" - mainContractColumn.state = "SETUP" - } - } - - Button { - id: debugButton - text: "Debug" - onClicked: { - var res = ui.debugTx("", txValue.text, txGas.text, txGasPrice.text, codeView.text) - debugWindow.visible = true - } - } - } - } - - // New Transaction component - Component { - id: newTransaction - Column { - id: simpleSendColumn - states: [ - State{ - name: "ERROR" - }, - State { - name: "DONE" - PropertyChanges { target: txSimpleValue; visible:false} - PropertyChanges { target: txSimpleRecipient; visible:false} - PropertyChanges { target:newSimpleTxButton; visible:false} - - PropertyChanges { target: txSimpleResult; visible:true} - PropertyChanges { target: txSimpleOutput; visible:true} - PropertyChanges { target:newSimpleTxButton; visible:true} - }, - State { - name: "SETUP" - PropertyChanges { target: txSimpleValue; visible:true; text: ""} - PropertyChanges { target: txSimpleRecipient; visible:true; text: ""} - PropertyChanges { target: txSimpleButton; visible:true} - PropertyChanges { target:newSimpleTxButton; visible:false} - } - ] - spacing: 5 - anchors.leftMargin: 5 - anchors.topMargin: 5 - anchors.top: parent.top - anchors.left: parent.left - - function checkFormState(){ - if(txSimpleRecipient.text.length == 40 && txSimpleValue.text.length > 0) { - txSimpleButton.state = "READY" - }else{ - txSimpleButton.state = "NOTREADY" - } - } - - TextField { - id: txSimpleRecipient - placeholderText: "Recipient address" - Layout.fillWidth: true - validator: RegExpValidator { regExp: /[a-f0-9]{40}/ } - width: 530 - onTextChanged: { checkFormState() } - } - TextField { - id: txSimpleValue - width: 200 - placeholderText: "Amount" - anchors.rightMargin: 5 - validator: RegExpValidator { regExp: /\d*/ } - onTextChanged: { checkFormState() } - } - Button { - id: txSimpleButton - /*enabled: false*/ - states: [ - State { - name: "READY" - PropertyChanges { target: txSimpleButton; /*enabled: true*/} - }, - State { - name: "NOTREADY" - PropertyChanges { target: txSimpleButton; /*enabled: false*/} - } - ] - text: "Send" - onClicked: { - //this.enabled = false - var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text,"","","") - if(res[1]) { - txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error() - } else { - txSimpleResult.text = "Your transaction has been broadcasted over the network.\nYour transaction id is:" - txSimpleOutput.text = res[0].hash - this.visible = false - simpleSendColumn.state = "DONE" - } - } - } - Text { - id: txSimpleResult - visible: false - - } - TextField { - id: txSimpleOutput - visible: false - width: 530 - } - Button { - id: newSimpleTxButton - visible: false - text: "Create an other transaction" - onClicked: { - this.visible = false - simpleSendColumn.state = "SETUP" - } - } - } - } + id: root + + width: 900 + height: 600 + minimumHeight: 300 + + title: "Ethereal" + + MenuBar { + Menu { + title: "File" + MenuItem { + text: "Import App" + shortcut: "Ctrl+o" + onTriggered: openAppDialog.open() + } + } + + Menu { + title: "Tools" + MenuItem { + text: "Muted" + shortcut: "Ctrl+e" + onTriggered: ui.muted("") + } + + MenuItem { + text: "Debugger" + shortcut: "Ctrl+d" + onTriggered: ui.startDebugger() + } + } + + Menu { + title: "Network" + MenuItem { + text: "Add Peer" + shortcut: "Ctrl+p" + onTriggered: { + addPeerWin.visible = true + } + } + + MenuItem { + text: "Start" + onTriggered: ui.connect() + } + } + + Menu { + title: "Help" + MenuItem { + text: "About" + onTriggered: { + aboutWin.visible = true + } + } + } + + } + + + property var blockModel: ListModel { + id: blockModel + } + + function setView(view) { + networkView.visible = false + historyView.visible = false + newTxView.visible = false + infoView.visible = false + view.visible = true + //root.title = "Ethereal - " = view.title + } + + SplitView { + anchors.fill: parent + resizing: false + + Rectangle { + id: menu + Layout.minimumWidth: 80 + Layout.maximumWidth: 80 + anchors.bottom: parent.bottom + anchors.top: parent.top + //color: "#D9DDE7" + color: "#252525" + + ColumnLayout { + y: 50 + anchors.left: parent.left + anchors.right: parent.right + height: 200 + Image { + source: ui.assetPath("tx.png") + anchors.horizontalCenter: parent.horizontalCenter + MouseArea { + anchors.fill: parent + onClicked: { + setView(historyView) + } + } + } + Image { + source: ui.assetPath("new.png") + anchors.horizontalCenter: parent.horizontalCenter + MouseArea { + anchors.fill: parent + onClicked: { + setView(newTxView) + } + } + } + Image { + source: ui.assetPath("net.png") + anchors.horizontalCenter: parent.horizontalCenter + MouseArea { + anchors.fill: parent + onClicked: { + setView(networkView) + } + } + } + + Image { + source: ui.assetPath("heart.png") + anchors.horizontalCenter: parent.horizontalCenter + MouseArea { + anchors.fill: parent + onClicked: { + setView(infoView) + } + } + } + } + } + + Rectangle { + id: mainView + color: "#00000000" + anchors.right: parent.right + anchors.left: menu.right + anchors.bottom: parent.bottom + anchors.top: parent.top + + property var txModel: ListModel { + id: txModel + } + + Rectangle { + id: historyView + anchors.fill: parent + + property var title: "Transactions" + TableView { + id: txTableView + anchors.fill: parent + TableViewColumn{ role: "inout" ; title: "" ; width: 40 } + TableViewColumn{ role: "value" ; title: "Value" ; width: 100 } + TableViewColumn{ role: "address" ; title: "Address" ; width: 430 } + TableViewColumn{ role: "contract" ; title: "Contract" ; width: 100 } + + model: txModel + } + } + + Rectangle { + id: newTxView + property var title: "New transaction" + visible: false + anchors.fill: parent + color: "#00000000" + TabView{ + anchors.fill: parent + anchors.rightMargin: 5 + anchors.leftMargin: 5 + anchors.topMargin: 5 + anchors.bottomMargin: 5 + id: newTransactionTab + Component.onCompleted:{ + addTab("Simple send", newTransaction) + addTab("Contracts", newContract) + } + } + } + + Rectangle { + id: networkView + property var title: "Network" + visible: false + anchors.fill: parent + + TableView { + id: blockTable + width: parent.width + anchors.top: parent.top + anchors.bottom: logView.top + TableViewColumn{ role: "number" ; title: "#" ; width: 100 } + TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } + TableViewColumn{ role: "txAmount" ; title: "Tx amount" ; width: 100 } + + model: blockModel + + onDoubleClicked: { + popup.visible = true + popup.setDetails(blockModel.get(row)) + } + } + + property var logModel: ListModel { + id: logModel + } + + TableView { + id: logView + width: parent.width + height: 150 + anchors.bottom: parent.bottom + TableViewColumn{ role: "description" ; title: "log" } + + model: logModel + } + } + + Rectangle { + id: infoView + property var title: "Information" + visible: false + color: "#00000000" + anchors.fill: parent + + Label { + id: addressLabel + text: "Address" + anchors { + margins: 5 + top: parent.top + left: parent.left + } + } + TextField { + anchors { + margins: 5 + left: addressLabel.right + top: parent.top + } + text: pub.getKey().address + width: 500 + } + } + + /* + signal addPlugin(string name) + Component { + id: pluginWindow + Rectangle { + anchors.fill: parent + Label { + id: pluginTitle + anchors.centerIn: parent + text: "Hello world" + } + Component.onCompleted: setView(this) + } + } + + onAddPlugin: { + var pluginWin = pluginWindow.createObject(mainView) + console.log(pluginWin) + pluginWin.pluginTitle.text = "Test" + } + */ + } + } + + FileDialog { + id: openAppDialog + title: "Open QML Application" + onAccepted: { + //ui.open(openAppDialog.fileUrl.toString()) + //ui.openHtml(Qt.resolvedUrl(ui.assetPath("test.html"))) + ui.openHtml(openAppDialog.fileUrl.toString()) + } + } + + statusBar: StatusBar { + RowLayout { + anchors.fill: parent + + Button { + property var enabled: true + id: debuggerWindow + onClicked: { + ui.startDebugger() + } + text: "Debugger" + } + + Button { + id: importAppButton + anchors.left: debuggerWindow.right + anchors.leftMargin: 5 + onClicked: openAppDialog.open() + text: "Import App" + } + + Label { + anchors.left: importAppButton.right + anchors.leftMargin: 5 + id: walletValueLabel + } + + Label { + anchors.right: peerImage.left + anchors.rightMargin: 5 + id: peerLabel + font.pixelSize: 8 + text: "0 / 0" + } + Image { + id: peerImage + anchors.right: parent.right + width: 10; height: 10 + source: ui.assetPath("network.png") + } + } + } + + Window { + id: popup + visible: false + property var block + width: root.width + height: 240 + x: root.x + y: root.y + root.height + Component{ + id: blockDetailsDelegate + Rectangle { + color: "#252525" + width: popup.width + height: 200 + Column { + anchors.leftMargin: 10 + anchors.topMargin: 5 + anchors.top: parent.top + anchors.left: parent.left + Text { text: '

Block details

'; color: "#F2F2F2"} + Text { text: 'Block number: ' + number; color: "#F2F2F2"} + Text { text: 'Hash: ' + hash; color: "#F2F2F2"} + Text { text: 'Block found at: ' + prettyTime; color: "#F2F2F2"} + } + } + } + ListView { + model: singleBlock + delegate: blockDetailsDelegate + anchors.top: parent.top + height: 70 + anchors.leftMargin: 20 + id: listViewThing + Layout.maximumHeight: 40 + } + TableView { + id: txView + anchors.top: listViewThing.bottom + anchors.topMargin: 50 + width: parent.width + + TableViewColumn{width: 90; role: "value" ; title: "Value" } + TableViewColumn{width: 200; role: "hash" ; title: "Hash" } + TableViewColumn{width: 200; role: "sender" ; title: "Sender" } + TableViewColumn{width: 200;role: "address" ; title: "Receiver" } + TableViewColumn{width: 60; role: "gas" ; title: "Gas" } + TableViewColumn{width: 60; role: "gasPrice" ; title: "Gas Price" } + TableViewColumn{width: 60; role: "isContract" ; title: "Contract" } + + model: transactionModel + onClicked: { + var tx = transactionModel.get(row) + if(tx.data) { + popup.showContractData(tx) + }else{ + popup.height = 230 + } + } + } + + function showContractData(tx) { + txDetailsDebugButton.tx = tx + if(tx.createsContract) { + contractData.text = tx.data + contractLabel.text = "

Transaction created contract " + tx.address + "

" + }else{ + contractLabel.text = "

Transaction ran contract " + tx.address + "

" + contractData.text = tx.rawData + } + popup.height = 400 + } + + Rectangle { + id: txDetails + width: popup.width + height: 300 + anchors.left: listViewThing.left + anchors.top: txView.bottom + Label { + text: "

Contract data

" + anchors.top: parent.top + anchors.left: parent.left + id: contractLabel + anchors.leftMargin: 10 + } + Button { + property var tx + id: txDetailsDebugButton + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.top: parent.top + anchors.topMargin: 10 + text: "Debug contract" + onClicked: { + if(tx.createsContract){ + ui.startDbWithCode(tx.rawData) + }else { + ui.startDbWithContractAndData(tx.address, tx.rawData) + } + } + } + TextArea { + id: contractData + text: "Contract" + anchors.top: contractLabel.bottom + anchors.left: parent.left + wrapMode: Text.Wrap + width: parent.width - 30 + height: 80 + anchors.leftMargin: 10 + } + } + property var transactionModel: ListModel { + id: transactionModel + } + property var singleBlock: ListModel { + id: singleBlock + } + function setDetails(block){ + singleBlock.set(0,block) + popup.height = 230 + transactionModel.clear() + if(block.txs != undefined){ + for(var i = 0; i < block.txs.count; ++i) { + transactionModel.insert(0, block.txs.get(i)) + } + if(block.txs.get(0).data){ + popup.showContractData(block.txs.get(0)) + } + } + txView.forceActiveFocus() + } + } + + Window { + id: addPeerWin + visible: false + minimumWidth: 230 + maximumWidth: 230 + maximumHeight: 50 + minimumHeight: 50 + + TextField { + id: addrField + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 10 + placeholderText: "address:port" + onAccepted: { + ui.connectToPeer(addrField.text) + addPeerWin.visible = false + } + } + Button { + anchors.left: addrField.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 5 + text: "Add" + onClicked: { + ui.connectToPeer(addrField.text) + addPeerWin.visible = false + } + } + Component.onCompleted: { + addrField.focus = true + } + } + + Window { + id: aboutWin + visible: false + title: "About" + minimumWidth: 350 + maximumWidth: 350 + maximumHeight: 200 + minimumHeight: 200 + + Image { + id: aboutIcon + height: 150 + width: 150 + fillMode: Image.PreserveAspectFit + smooth: true + source: ui.assetPath("facet.png") + x: 10 + y: 10 + } + + Text { + anchors.left: aboutIcon.right + anchors.leftMargin: 10 + font.pointSize: 12 + text: "

Ethereal


Development

Jeffrey Wilcke
Maran Hidskes
" + } + + } + + ApplicationWindow { + id: debugWindow + visible: false + title: "Debugger" + minimumWidth: 600 + minimumHeight: 600 + width: 800 + height: 600 + + + Item { + id: keyHandler + focus: true + Keys.onPressed: { + if (event.key == Qt.Key_Space) { + ui.next() + } + } + } + SplitView { + anchors.fill: parent + property var asmModel: ListModel { + id: asmModel + } + TableView { + id: asmTableView + width: 200 + TableViewColumn{ role: "value" ; title: "" ; width: 100 } + model: asmModel + } + + Rectangle { + anchors.left: asmTableView.right + anchors.right: parent.right + SplitView { + orientation: Qt.Vertical + anchors.fill: parent + + TableView { + property var memModel: ListModel { + id: memModel + } + height: parent.height/2 + width: parent.width + TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} + TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} + model: memModel + } + + SplitView { + orientation: Qt.Horizontal + id: debugSplitView + TableView { + property var debuggerLog: ListModel { + id: debuggerLog + } + TableViewColumn{ role: "value"; title: "Debug messages" } + model: debuggerLog + } + TableView { + property var stackModel: ListModel { + id: stackModel + } + height: parent.height/2 + width: parent.width + TableViewColumn{ role: "value" ; title: "Stack" ; width: debugSplitView.width } + model: stackModel + } + } + } + } + } + statusBar: StatusBar { + RowLayout { + anchors.fill: parent + Button { + property var enabled: true + id: debugNextButton + onClicked: { + ui.next() + } + text: "Next" + } + } + } + } + + function setAsm(asm) { + asmModel.append({asm: asm}) + } + + function setInstruction(num) { + asmTableView.selection.clear() + asmTableView.selection.select(num-1) + } + + function clearAsm() { + asmModel.clear() + } + + function setMem(mem) { + memModel.append({num: mem.num, value: mem.value}) + } + function clearMem(){ + memModel.clear() + } + + function setStack(stack) { + stackModel.append({value: stack}) + } + function addDebugMessage(message){ + console.log("WOOP:") + debuggerLog.append({value: message}) + } + + function clearStack() { + stackModel.clear() + } + + function loadPlugin(name) { + console.log("Loading plugin" + name) + mainView.addPlugin(name) + } + + function setWalletValue(value) { + walletValueLabel.text = value + } + + function addTx(tx, inout) { + var isContract + if (tx.contract == true){ + isContract = "Yes" + }else{ + isContract = "No" + } + txModel.insert(0, {inout: inout, hash: tx.hash, address: tx.address, value: tx.value, contract: isContract}) + } + + function addBlock(block, initial) { + var txs = JSON.parse(block.transactions); + var amount = 0 + if(initial == undefined){ + initial = false + } + + if(txs != null){ + amount = txs.length + } + + if(initial){ + blockModel.append({number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) + }else{ + blockModel.insert(0, {number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) + } + } + + function addLog(str) { + if(str.len != 0) { + logModel.append({description: str}) + } + } + + function setPeers(text) { + peerLabel.text = text + } + function convertToPretty(unixTs){ + var a = new Date(unixTs*1000); + var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; + var year = a.getFullYear(); + var month = months[a.getMonth()]; + var date = a.getDate(); + var hour = a.getHours(); + var min = a.getMinutes(); + var sec = a.getSeconds(); + var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; + return time; + } + // ******************************************* + // Components + // ******************************************* + + // New Contract component + Component { + id: newContract + Column { + id: mainContractColumn + function contractFormReady(){ + if(codeView.text.length > 0 && txValue.text.length > 0 && txGas.text.length > 0 && txGasPrice.length > 0) { + txButton.state = "READY" + }else{ + txButton.state = "NOTREADY" + } + } + states: [ + State{ + name: "ERROR" + PropertyChanges { target: txResult; visible:true} + PropertyChanges { target: codeView; visible:true} + }, + State { + name: "DONE" + PropertyChanges { target: txValue; visible:false} + PropertyChanges { target: txGas; visible:false} + PropertyChanges { target: txGasPrice; visible:false} + PropertyChanges { target: codeView; visible:false} + PropertyChanges { target: txButton; visible:false} + PropertyChanges { target: txDataLabel; visible:false} + + PropertyChanges { target: txResult; visible:true} + PropertyChanges { target: txOutput; visible:true} + PropertyChanges { target: newTxButton; visible:true} + }, + State { + name: "SETUP" + PropertyChanges { target: txValue; visible:true; text: ""} + PropertyChanges { target: txGas; visible:true; text: ""} + PropertyChanges { target: txGasPrice; visible:true; text: ""} + PropertyChanges { target: codeView; visible:true; text: ""} + PropertyChanges { target: txButton; visible:true} + PropertyChanges { target: txDataLabel; visible:true} + + PropertyChanges { target: txResult; visible:false} + PropertyChanges { target: txOutput; visible:false} + PropertyChanges { target: newTxButton; visible:false} + } + ] + width: 400 + spacing: 5 + anchors.left: parent.left + anchors.top: parent.top + anchors.leftMargin: 5 + anchors.topMargin: 5 + + TextField { + id: txValue + width: 200 + placeholderText: "Amount" + validator: RegExpValidator { regExp: /\d*/ } + onTextChanged: { + contractFormReady() + } + } + TextField { + id: txGas + width: 200 + validator: RegExpValidator { regExp: /\d*/ } + placeholderText: "Gas" + onTextChanged: { + contractFormReady() + } + } + TextField { + id: txGasPrice + width: 200 + placeholderText: "Gas price" + validator: RegExpValidator { regExp: /\d*/ } + onTextChanged: { + contractFormReady() + } + } + + Row { + id: rowContract + ExclusiveGroup { id: contractTypeGroup } + RadioButton { + id: createContractRadio + text: "Create contract" + checked: true + exclusiveGroup: contractTypeGroup + onClicked: { + txFuelRecipient.visible = false + txDataLabel.text = "Contract code" + } + } + RadioButton { + id: runContractRadio + text: "Run contract" + exclusiveGroup: contractTypeGroup + onClicked: { + txFuelRecipient.visible = true + txDataLabel.text = "Contract arguments" + } + } + } + + + Label { + id: txDataLabel + text: "Contract code" + } + + TextArea { + id: codeView + height: 300 + anchors.topMargin: 5 + Layout.fillWidth: true + width: parent.width /2 + onTextChanged: { + contractFormReady() + } + } + + TextField { + id: txFuelRecipient + placeholderText: "Contract address" + validator: RegExpValidator { regExp: /[a-f0-9]{40}/ } + visible: false + width: 530 + } + + Button { + id: txButton + /* enabled: false */ + states: [ + State { + name: "READY" + PropertyChanges { target: txButton; /*enabled: true*/} + }, + State { + name: "NOTREADY" + PropertyChanges { target: txButton; /*enabled:false*/} + } + ] + text: "Send" + onClicked: { + //this.enabled = false + var res = eth.create(txFuelRecipient.text, txValue.text, txGas.text, txGasPrice.text, codeView.text) + if(res[1]) { + txResult.text = "Your contract could not be send over the network:\n" + txResult.text += res[1].error() + txResult.text += "" + mainContractColumn.state = "ERROR" + } else { + txResult.text = "Your transaction has been submitted:\n" + txOutput.text = res[0].address + mainContractColumn.state = "DONE" + } + } + } + Text { + id: txResult + visible: false + } + TextField { + id: txOutput + visible: false + width: 530 + } + Button { + id: newTxButton + visible: false + text: "Create an other contract" + onClicked: { + this.visible = false + txResult.text = "" + txOutput.text = "" + mainContractColumn.state = "SETUP" + } + } + + Button { + id: debugButton + text: "Debug" + onClicked: { + var res = ui.debugTx("", txValue.text, txGas.text, txGasPrice.text, codeView.text) + debugWindow.visible = true + } + } + } + } + + // New Transaction component + Component { + id: newTransaction + Column { + id: simpleSendColumn + states: [ + State{ + name: "ERROR" + }, + State { + name: "DONE" + PropertyChanges { target: txSimpleValue; visible:false} + PropertyChanges { target: txSimpleRecipient; visible:false} + PropertyChanges { target:newSimpleTxButton; visible:false} + + PropertyChanges { target: txSimpleResult; visible:true} + PropertyChanges { target: txSimpleOutput; visible:true} + PropertyChanges { target:newSimpleTxButton; visible:true} + }, + State { + name: "SETUP" + PropertyChanges { target: txSimpleValue; visible:true; text: ""} + PropertyChanges { target: txSimpleRecipient; visible:true; text: ""} + PropertyChanges { target: txSimpleButton; visible:true} + PropertyChanges { target:newSimpleTxButton; visible:false} + } + ] + spacing: 5 + anchors.leftMargin: 5 + anchors.topMargin: 5 + anchors.top: parent.top + anchors.left: parent.left + + function checkFormState(){ + if(txSimpleRecipient.text.length == 40 && txSimpleValue.text.length > 0) { + txSimpleButton.state = "READY" + }else{ + txSimpleButton.state = "NOTREADY" + } + } + + TextField { + id: txSimpleRecipient + placeholderText: "Recipient address" + Layout.fillWidth: true + validator: RegExpValidator { regExp: /[a-f0-9]{40}/ } + width: 530 + onTextChanged: { checkFormState() } + } + TextField { + id: txSimpleValue + width: 200 + placeholderText: "Amount" + anchors.rightMargin: 5 + validator: RegExpValidator { regExp: /\d*/ } + onTextChanged: { checkFormState() } + } + Button { + id: txSimpleButton + /*enabled: false*/ + states: [ + State { + name: "READY" + PropertyChanges { target: txSimpleButton; /*enabled: true*/} + }, + State { + name: "NOTREADY" + PropertyChanges { target: txSimpleButton; /*enabled: false*/} + } + ] + text: "Send" + onClicked: { + //this.enabled = false + var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text,"","","") + if(res[1]) { + txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error() + } else { + txSimpleResult.text = "Your transaction has been broadcasted over the network.\nYour transaction id is:" + txSimpleOutput.text = res[0].hash + this.visible = false + simpleSendColumn.state = "DONE" + } + } + } + Text { + id: txSimpleResult + visible: false + + } + TextField { + id: txSimpleOutput + visible: false + width: 530 + } + Button { + id: newSimpleTxButton + visible: false + text: "Create an other transaction" + onClicked: { + this.visible = false + simpleSendColumn.state = "SETUP" + } + } + } + } } diff --git a/ethereal/assets/samplecoin/samplecoin.html b/ethereal/assets/samplecoin/samplecoin.html index e780aefb43..dc8d0b7e96 100644 --- a/ethereal/assets/samplecoin/samplecoin.html +++ b/ethereal/assets/samplecoin/samplecoin.html @@ -9,7 +9,7 @@