diff options
author | obscuren <geffobscura@gmail.com> | 2014-05-13 22:37:47 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-05-13 22:37:47 +0800 |
commit | 1adfc272a856d466e3d513522ee2fa83853b08ab (patch) | |
tree | 1618746391e6302d65401581e9804b7900cfbd45 /ethereal | |
parent | 721d3a9a57fbc7478255d52271531f001375b863 (diff) | |
parent | 9caf53f8c63cb30a174d2b33ef85176c8f6f8204 (diff) | |
download | dexon-1adfc272a856d466e3d513522ee2fa83853b08ab.tar.gz dexon-1adfc272a856d466e3d513522ee2fa83853b08ab.tar.zst dexon-1adfc272a856d466e3d513522ee2fa83853b08ab.zip |
Merge branch 'release/poc5-rc4'
Diffstat (limited to 'ethereal')
-rw-r--r-- | ethereal/assets/ext/ethereum.js | 17 | ||||
-rw-r--r-- | ethereal/assets/qml/first_run.qml | 262 | ||||
-rw-r--r-- | ethereal/assets/qml/webapp.qml | 31 | ||||
-rw-r--r-- | ethereal/assets/util/test.html | 43 | ||||
-rw-r--r-- | ethereal/config.go | 2 | ||||
-rw-r--r-- | ethereal/ethereum.go | 14 | ||||
-rw-r--r-- | ethereal/ui/ext_app.go | 2 | ||||
-rw-r--r-- | ethereal/ui/gui.go | 117 |
8 files changed, 323 insertions, 165 deletions
diff --git a/ethereal/assets/ext/ethereum.js b/ethereal/assets/ext/ethereum.js index f565e58bd..d4eaf97fd 100644 --- a/ethereal/assets/ext/ethereum.js +++ b/ethereal/assets/ext/ethereum.js @@ -36,6 +36,21 @@ window.eth = { postData({call: "getKey"}, cb); }, + getTxCountAt: function(address, cb) { + postData({call: "getTxCountAt", args: [address]}, cb); + }, + getIsMining: function(cb){ + postData({call: "getIsMining"}, cb) + }, + getIsListening: function(cb){ + postData({call: "getIsListening"}, cb) + }, + getCoinBase: function(cb){ + postData({call: "getCoinBase"}, cb); + }, + getPeerCount: function(cb){ + postData({call: "getPeerCount"}, cb); + }, getBalanceAt: function(address, cb) { postData({call: "getBalance", args: [address]}, cb); }, @@ -115,6 +130,8 @@ window.eth = { } } }, + + } window.eth._callbacks = {} window.eth._onCallbacks = {} diff --git a/ethereal/assets/qml/first_run.qml b/ethereal/assets/qml/first_run.qml index 0bd3b4ce1..0b1dac4c6 100644 --- a/ethereal/assets/qml/first_run.qml +++ b/ethereal/assets/qml/first_run.qml @@ -10,146 +10,146 @@ import QtQuick.Controls.Styles 1.1 import QtQuick.Dialogs 1.1 ApplicationWindow { - id: wizardRoot - width: 500 - height: 400 - title: "Ethereal first run setup" + id: wizardRoot + width: 500 + height: 400 + title: "Ethereal first run setup" - Column { - spacing: 5 - anchors.leftMargin: 10 - anchors.left: parent.left + Column { + spacing: 5 + anchors.leftMargin: 10 + anchors.left: parent.left - Text { - visible: true - text: "<h2>Ethereal setup</h2>" - } + Text { + visible: true + text: "<h2>Ethereal setup</h2>" + } - Column { - id: restoreColumn - spacing: 5 - Text { - visible: true - font.pointSize: 14 - text: "Restore your Ethereum account" - id: restoreLabel - } + Column { + id: restoreColumn + spacing: 5 + Text { + visible: true + font.pointSize: 14 + text: "Restore your Ethereum account" + id: restoreLabel + } - TextField { - id: txPrivKey - width: 480 - placeholderText: "Private key or mnemonic words" - focus: true - onTextChanged: { - if(this.text.length == 64){ - detailLabel.text = "Private (hex) key detected." - actionButton.enabled = true - } - else if(this.text.split(" ").length == 24){ - detailLabel.text = "Mnemonic key detected." - actionButton.enabled = true - }else{ - detailLabel.text = "" - actionButton.enabled = false - } + TextField { + id: txPrivKey + width: 480 + placeholderText: "Private key or mnemonic words" + focus: true + onTextChanged: { + if(this.text.length == 64){ + detailLabel.text = "Private (hex) key detected." + actionButton.enabled = true + } + else if(this.text.split(" ").length == 24){ + detailLabel.text = "Mnemonic key detected." + actionButton.enabled = true + }else{ + detailLabel.text = "" + actionButton.enabled = false + } + } + } + Row { + spacing: 10 + Button { + id: actionButton + text: "Restore" + enabled: false + onClicked: { + var success = lib.importAndSetPrivKey(txPrivKey.text) + if(success){ + importedDetails.visible = true + restoreColumn.visible = false + newKey.visible = false + wizardRoot.height = 120 + } + } + } + Text { + id: detailLabel + font.pointSize: 12 + anchors.topMargin: 10 + } + } } - } - Row { - spacing: 10 - Button { - id: actionButton - text: "Restore" - enabled: false - onClicked: { - var success = eth.importAndSetPrivKey(txPrivKey.text) - if(success){ - importedDetails.visible = true - restoreColumn.visible = false - newKey.visible = false - wizardRoot.height = 120 - } - } + Column { + id: importedDetails + visible: false + Text { + text: "<b>Your account has been imported. Please close the application and restart it again to let the changes take effect.</b>" + wrapMode: Text.WordWrap + width: 460 + } } - Text { - id: detailLabel - font.pointSize: 12 - anchors.topMargin: 10 + Column { + spacing: 5 + id: newDetailsColumn + visible: false + Text { + font.pointSize: 14 + text: "Your account details" + } + Label { + text: "Address" + } + TextField { + id: addressInput + readOnly:true + width: 480 + } + Label { + text: "Private key" + } + TextField { + id: privkeyInput + readOnly:true + width: 480 + } + Label { + text: "Mnemonic words" + } + TextField { + id: mnemonicInput + readOnly:true + width: 480 + } + Label { + text: "<b>A new account has been created. Please take the time to write down the <i>24 words</i>. You can use those to restore your account at a later date.</b>" + wrapMode: Text.WordWrap + width: 480 + } + Label { + text: "Please restart the application once you have completed the steps above." + wrapMode: Text.WordWrap + width: 480 + } } - } - } - Column { - id: importedDetails - visible: false - Text { - text: "<b>Your account has been imported. Please close the application and restart it again to let the changes take effect.</b>" - wrapMode: Text.WordWrap - width: 460 - } - } - Column { - spacing: 5 - id: newDetailsColumn - visible: false - Text { - font.pointSize: 14 - text: "Your account details" - } - Label { - text: "Address" - } - TextField { - id: addressInput - readOnly:true - width: 480 - } - Label { - text: "Private key" - } - TextField { - id: privkeyInput - readOnly:true - width: 480 - } - Label { - text: "Mnemonic words" - } - TextField { - id: mnemonicInput - readOnly:true - width: 480 - } - Label { - text: "<b>A new account has been created. Please take the time to write down the <i>24 words</i>. You can use those to restore your account at a later date.</b>" - wrapMode: Text.WordWrap - width: 480 - } - Label { - text: "Please restart the application once you have completed the steps above." - wrapMode: Text.WordWrap - width: 480 - } - } - } - Button { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.rightMargin: 10 - anchors.bottomMargin: 10 - id: newKey - text: "I don't have an account yet" - onClicked: { - var res = eth.createAndSetPrivKey() - mnemonicInput.text = res[0] - addressInput.text = res[1] - privkeyInput.text = res[2] + } + Button { + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.rightMargin: 10 + anchors.bottomMargin: 10 + id: newKey + text: "I don't have an account yet" + onClicked: { + var res = lib.createAndSetPrivKey() + mnemonicInput.text = res[0] + addressInput.text = res[1] + privkeyInput.text = res[2] - // Hide restore - restoreColumn.visible = false + // Hide restore + restoreColumn.visible = false - // Show new details - newDetailsColumn.visible = true - newKey.visible = false + // Show new details + newDetailsColumn.visible = true + newKey.visible = false + } } - } } diff --git a/ethereal/assets/qml/webapp.qml b/ethereal/assets/qml/webapp.qml index 1f3c3874a..7af006f77 100644 --- a/ethereal/assets/qml/webapp.qml +++ b/ethereal/assets/qml/webapp.qml @@ -47,13 +47,37 @@ ApplicationWindow { 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("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") + var block = eth.getBlock("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") postData(data._seed, block) + break case "getBlockByHash": - var block = eth.getBlock("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") + var block = eth.getBlock("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") postData(data._seed, block) + break case "transact": require(5) @@ -94,11 +118,14 @@ ApplicationWindow { 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) diff --git a/ethereal/assets/util/test.html b/ethereal/assets/util/test.html new file mode 100644 index 000000000..d458e6670 --- /dev/null +++ b/ethereal/assets/util/test.html @@ -0,0 +1,43 @@ +<html> +<head> +<title>Utils</title> +</head> +<body onload="init();"> +<label>Nonce for 2ef47100e0787b915105fd5e3f4ff6752079d5cb</label> +<p id="nonce"></p> + +<label>Connected peers</label> +<p id="peers"></p> + +<label>Is mining</label> +<p id="isMining"></p> + +<label>Is listening</label> +<p id="isListen"></p> + +<label>Coinbase</label> +<p id="coinbase"></p> + +<script type="text/javascript"> + +function init() { + eth.getTxCountAt("2ef47100e0787b915105fd5e3f4ff6752079d5cb", function(nonce){ + document.querySelector("#nonce").innerHTML = nonce; + }) + eth.getPeerCount(function(peerLength){ + document.querySelector("#peers").innerHTML = peerLength; + }) + eth.getIsMining(function(mining){ + document.querySelector("#isMining").innerHTML = mining; + }) + eth.getIsListening(function(listen){ + document.querySelector("#isListen").innerHTML = listen; + }) + eth.getCoinBase(function(address){ + document.querySelector("#coinbase").innerHTML = address; + }) +} +</script> +</body> +</html> + diff --git a/ethereal/config.go b/ethereal/config.go index 94f896c5f..e4bdb0a00 100644 --- a/ethereal/config.go +++ b/ethereal/config.go @@ -7,6 +7,7 @@ import ( var StartConsole bool var StartMining bool var StartRpc bool +var RpcPort int var UseUPnP bool var OutboundPort string var ShowGenesis bool @@ -28,6 +29,7 @@ func Init() { flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.BoolVar(&ExportKey, "export", false, "export private key") + flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") flag.StringVar(&OutboundPort, "p", "30303", "listening port") flag.StringVar(&DataDir, "dir", ".ethereal", "ethereum data directory") flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)") diff --git a/ethereal/ethereum.go b/ethereal/ethereum.go index 8b8889e37..15a454bdf 100644 --- a/ethereal/ethereum.go +++ b/ethereal/ethereum.go @@ -100,8 +100,12 @@ func main() { } if StartRpc { - ethereum.RpcServer = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool())) - go ethereum.RpcServer.Start() + ethereum.RpcServer, err = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum), RpcPort) + if err != nil { + log.Println("Could not start RPC interface:", err) + } else { + go ethereum.RpcServer.Start() + } } log.Printf("Starting Ethereum GUI v%s\n", ethutil.Config.Ver) @@ -110,5 +114,11 @@ func main() { ethereum.MaxPeers = MaxPeer gui := ethui.New(ethereum) + + ethereum.Start(UseSeed) + gui.Start(AssetPath) + + // Wait for shutdown + ethereum.WaitForShutdown() } diff --git a/ethereal/ui/ext_app.go b/ethereal/ui/ext_app.go index 93db0ade1..de5f15db6 100644 --- a/ethereal/ui/ext_app.go +++ b/ethereal/ui/ext_app.go @@ -34,7 +34,7 @@ type ExtApplication struct { func NewExtApplication(container AppContainer, lib *UiLib) *ExtApplication { app := &ExtApplication{ - ethpub.NewPEthereum(lib.eth.StateManager(), lib.eth.BlockChain(), lib.eth.TxPool()), + ethpub.NewPEthereum(lib.eth), make(chan ethutil.React, 1), make(chan ethutil.React, 1), make(chan bool), diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 46bfa0133..7f84272d6 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -24,7 +24,8 @@ type Gui struct { eth *eth.Ethereum // The public Ethereum library - lib *EthLib + lib *EthLib + uiLib *UiLib txDb *ethdb.LDBDatabase @@ -52,7 +53,7 @@ func New(ethereum *eth.Ethereum) *Gui { //ethereum.StateManager().WatchAddr(addr) } - pub := ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool()) + pub := ethpub.NewPEthereum(ethereum) return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub} } @@ -67,7 +68,7 @@ func (gui *Gui) Start(assetPath string) { Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, }}) - ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC3")) + ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC4")) ethutil.Config.Log.Infoln("[GUI] Starting GUI") // Create a new QML engine gui.engine = qml.NewEngine() @@ -75,19 +76,55 @@ func (gui *Gui) Start(assetPath string) { // Expose the eth library and the ui library to QML context.SetVar("eth", gui) - uiLib := NewUiLib(gui.engine, gui.eth, assetPath) - context.SetVar("ui", uiLib) + gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath) + context.SetVar("ui", gui.uiLib) // Load the main QML interface data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) - var err error - var component qml.Object - firstRun := len(data) == 0 + /* + var err error + var component qml.Object + firstRun := len(data) == 0 + + if firstRun { + component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) + } else { + component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) + } + if err != nil { + ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") + + panic(err) + } + + gui.win = component.CreateWindow(nil) + uiLib.win = gui.win + db := &Debugger{gui.win, make(chan bool)} + gui.lib.Db = db + uiLib.Db = db + + // Add the ui as a log system so we can log directly to the UGI + ethutil.Config.Log.AddLogSystem(gui) + + // Loads previous blocks + if firstRun == false { + go gui.setInitialBlockChain() + go gui.readPreviousTransactions() + go gui.update() + } - if firstRun { - component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) + gui.win.Show() + gui.win.Wait() + + gui.eth.Stop() + */ + + var win *qml.Window + var err error + if len(data) == 0 { + win, err = gui.showKeyImport(context) } else { - component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) + win, err = gui.showWallet(context) } if err != nil { ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") @@ -95,26 +132,48 @@ func (gui *Gui) Start(assetPath string) { panic(err) } - gui.win = component.CreateWindow(nil) - uiLib.win = gui.win - db := &Debugger{gui.win, make(chan bool)} - gui.lib.Db = db - uiLib.Db = db + win.Show() + win.Wait() + + gui.eth.Stop() +} + +func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) { + component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml")) + if err != nil { + return nil, err + } - // Add the ui as a log system so we can log directly to the UGI - ethutil.Config.Log.AddLogSystem(gui) + win := gui.createWindow(component) - // Loads previous blocks - if firstRun == false { - go gui.setInitialBlockChain() - go gui.readPreviousTransactions() - go gui.update() + go gui.setInitialBlockChain() + go gui.readPreviousTransactions() + go gui.update() + + return win, nil +} + +func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) { + context.SetVar("lib", gui.lib) + component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml")) + if err != nil { + return nil, err } - gui.win.Show() - gui.win.Wait() + return gui.createWindow(component), nil +} - gui.eth.Stop() +func (gui *Gui) createWindow(comp qml.Object) *qml.Window { + win := comp.CreateWindow(nil) + + gui.win = win + gui.uiLib.win = win + + db := &Debugger{gui.win, make(chan bool)} + gui.lib.Db = db + gui.uiLib.Db = db + + return gui.win } func (gui *Gui) setInitialBlockChain() { @@ -148,7 +207,7 @@ func (gui *Gui) update() { state := gui.eth.StateManager().TransState() unconfirmedFunds := new(big.Int) - gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetStateObject(gui.addr).Amount))) + gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.addr).Amount))) for { select { @@ -156,7 +215,7 @@ func (gui *Gui) update() { tx := txMsg.Tx if txMsg.Type == ethchain.TxPre { - object := state.GetStateObject(gui.addr) + object := state.GetAccount(gui.addr) if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce { gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) @@ -182,7 +241,7 @@ func (gui *Gui) update() { gui.win.Root().Call("setWalletValue", str) } else { - object := state.GetStateObject(gui.addr) + object := state.GetAccount(gui.addr) if bytes.Compare(tx.Sender(), gui.addr) == 0 { object.SubAmount(tx.Value) } else if bytes.Compare(tx.Recipient, gui.addr) == 0 { |