diff --git a/ethereal/assets/ethereum.js b/ethereal/assets/ethereum.js index fefad584a..0f9f68c43 100644 --- a/ethereal/assets/ethereum.js +++ b/ethereal/assets/ethereum.js @@ -47,6 +47,10 @@ window.eth = { postData({call: "getKey"}, cb); }, + watch: function(address) { + postData({call: "watch", args: [address]}); + }, + on: function(event, cb) { if(eth._onCallbacks[event] === undefined) { diff --git a/ethereal/assets/qml/webapp.qml b/ethereal/assets/qml/webapp.qml index 9cf154e9b..c34e0dc55 100644 --- a/ethereal/assets/qml/webapp.qml +++ b/ethereal/assets/qml/webapp.qml @@ -74,14 +74,24 @@ ApplicationWindow { var keys = eth.getKey() postData(data._seed, keys) break + case "watch": + if(data.args.length > 0) { + eth.watch(data.args[0]); + } } } 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) { - webview.experimental.postMessage(JSON.stringify({data: block, _event: "block:new"})) + postEvent("block:new", block) + } + function onObjectChangeCb(stateObject) { + postEvent("object:change", stateObject) } } diff --git a/ethereal/assets/samplecoin.html b/ethereal/assets/samplecoin.html index 476283f60..1b89be877 100644 --- a/ethereal/assets/samplecoin.html +++ b/ethereal/assets/samplecoin.html @@ -22,12 +22,15 @@ function tests() { } function init() { + eth.watch(jefcoinAddr); + eth.getKey(function(key) { eth.getStorage(jefcoinAddr, key, function(storage) { document.querySelector("#currentAmount").innerHTML = "Amount: " + storage; }); - eth.on("block:new", function() { + eth.on("object:change", function(stateObject) { + debug(stateObject); eth.getStorage(jefcoinAddr, key, function(storage) { document.querySelector("#currentAmount").innerHTML = "Amount: " + storage; }); diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 80498d718..d3a179496 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -2,7 +2,6 @@ package ethui import ( "bytes" - "encoding/hex" "fmt" "github.com/ethereum/eth-go" "github.com/ethereum/eth-go/ethchain" @@ -13,45 +12,6 @@ import ( "strings" ) -// Block interface exposed to QML -type Block struct { - Number int - Hash string -} - -type Tx struct { - Value, Hash, Address string - Contract bool -} - -type Key struct { - Address string -} - -type KeyRing struct { - Keys []interface{} -} - -func NewKeyRing(keys []interface{}) *KeyRing { - return &KeyRing{Keys: keys} -} - -func NewTxFromTransaction(tx *ethchain.Transaction) *Tx { - hash := hex.EncodeToString(tx.Hash()) - sender := hex.EncodeToString(tx.Recipient) - isContract := len(tx.Data) > 0 - - return &Tx{Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: sender, Contract: isContract} -} - -// Creates a new QML Block from a chain block -func NewBlockFromBlock(block *ethchain.Block) *Block { - info := block.BlockInfo() - hash := hex.EncodeToString(block.Hash()) - - return &Block{Number: int(info.Number), Hash: hash} -} - type Gui struct { // The main application window win *qml.Window @@ -96,9 +56,9 @@ func (ui *Gui) Start(assetPath string) { // Register ethereum functions qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ - Init: func(p *Block, obj qml.Object) { p.Number = 0; p.Hash = "" }, + Init: func(p *QBlock, obj qml.Object) { p.Number = 0; p.Hash = "" }, }, { - Init: func(p *Tx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, + Init: func(p *QTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, }}) ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.1")) @@ -169,13 +129,13 @@ func (ui *Gui) readPreviousTransactions() { for it.Next() { tx := ethchain.NewTransactionFromBytes(it.Value()) - ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) + ui.win.Root().Call("addTx", NewQTx(tx)) } it.Release() } func (ui *Gui) ProcessBlock(block *ethchain.Block) { - ui.win.Root().Call("addBlock", NewBlockFromBlock(block)) + ui.win.Root().Call("addBlock", NewQBlock(block)) } // Simple go routine function that updates the list of peers in the GUI @@ -193,13 +153,13 @@ func (ui *Gui) update() { if txMsg.Type == ethchain.TxPre { if bytes.Compare(tx.Sender(), ui.addr) == 0 { - ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) + ui.win.Root().Call("addTx", NewQTx(tx)) ui.txDb.Put(tx.Hash(), tx.RlpEncode()) ui.eth.StateManager().GetAddrState(ui.addr).Nonce += 1 unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) } else if bytes.Compare(tx.Recipient, ui.addr) == 0 { - ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) + ui.win.Root().Call("addTx", NewQTx(tx)) ui.txDb.Put(tx.Hash(), tx.RlpEncode()) unconfirmedFunds.Add(unconfirmedFunds, tx.Value) diff --git a/ethereal/ui/library.go b/ethereal/ui/library.go index 5ca2b4273..7f667f2c1 100644 --- a/ethereal/ui/library.go +++ b/ethereal/ui/library.go @@ -67,6 +67,10 @@ func (lib *EthLib) GetStateObject(address string) *Contract { return NewContract(stateObject) } +func (lib *EthLib) Watch(addr string) { + lib.stateManager.Watch(ethutil.FromHex(addr)) +} + func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) { var hash []byte var contractCreation bool @@ -117,7 +121,7 @@ func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, dataStr st return ethutil.Hex(tx.Hash()), nil } -func (lib *EthLib) GetBlock(hexHash string) *Block { +func (lib *EthLib) GetBlock(hexHash string) *QBlock { hash, err := hex.DecodeString(hexHash) if err != nil { return nil @@ -125,5 +129,5 @@ func (lib *EthLib) GetBlock(hexHash string) *Block { block := lib.blockChain.GetBlock(hash) - return &Block{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} + return &QBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} } diff --git a/ethereal/ui/types.go b/ethereal/ui/types.go new file mode 100644 index 000000000..5c39f0217 --- /dev/null +++ b/ethereal/ui/types.go @@ -0,0 +1,56 @@ +package ethui + +import ( + "encoding/hex" + "github.com/ethereum/eth-go/ethchain" + "github.com/ethereum/eth-go/ethutil" +) + +// Block interface exposed to QML +type QBlock struct { + Number int + Hash string +} + +// Creates a new QML Block from a chain block +func NewQBlock(block *ethchain.Block) *QBlock { + info := block.BlockInfo() + hash := hex.EncodeToString(block.Hash()) + + return &QBlock{Number: int(info.Number), Hash: hash} +} + +type QTx struct { + Value, Hash, Address string + Contract bool +} + +func NewQTx(tx *ethchain.Transaction) *QTx { + hash := hex.EncodeToString(tx.Hash()) + sender := hex.EncodeToString(tx.Recipient) + isContract := len(tx.Data) > 0 + + return &QTx{Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: sender, Contract: isContract} +} + +type QKey struct { + Address string +} + +type QKeyRing struct { + Keys []interface{} +} + +func NewQKeyRing(keys []interface{}) *QKeyRing { + return &QKeyRing{Keys: keys} +} + +type QStateObject struct { + Address string + Amount string + Nonce int +} + +func NewQStateObject(stateObject *ethchain.StateObject) *QStateObject { + return &QStateObject{ethutil.Hex(stateObject.Address()), stateObject.Amount.String(), int(stateObject.Nonce)} +} diff --git a/ethereal/ui/ui_lib.go b/ethereal/ui/ui_lib.go index 08e2267a7..6217c0065 100644 --- a/ethereal/ui/ui_lib.go +++ b/ethereal/ui/ui_lib.go @@ -69,8 +69,10 @@ func (ui *UiLib) OpenHtml(path string) { } win.Set("url", path) + webView := win.ObjectByName("webView") go func() { blockChan := make(chan ethutil.React, 1) + addrChan := make(chan ethutil.React, 1) quitChan := make(chan bool) go func() { @@ -82,8 +84,12 @@ func (ui *UiLib) OpenHtml(path string) { break out case block := <-blockChan: if block, ok := block.Resource.(*ethchain.Block); ok { - b := &Block{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} - win.ObjectByName("webView").Call("onNewBlockCb", b) + b := &QBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} + webView.Call("onNewBlockCb", b) + } + case stateObject := <-addrChan: + if stateObject, ok := stateObject.Resource.(*ethchain.StateObject); ok { + webView.Call("onObjectChangeCb", NewQStateObject(stateObject)) } } } @@ -93,6 +99,7 @@ func (ui *UiLib) OpenHtml(path string) { close(quitChan) }() ui.eth.Reactor().Subscribe("newBlock", blockChan) + ui.eth.Reactor().Subscribe("addressChanged", addrChan) win.Show() win.Wait() @@ -169,7 +176,7 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr), ethutil.Big(valueStr)) block := ui.eth.BlockChain().CurrentBlock - vm := ethchain.NewVm(state, ethchain.RuntimeVars{ + vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{ Origin: account.Address(), BlockNumber: block.BlockInfo().Number, PrevHash: block.PrevHash, diff --git a/ethereum/ethereum.go b/ethereum/ethereum.go index 881f39ece..04851d2bd 100644 --- a/ethereum/ethereum.go +++ b/ethereum/ethereum.go @@ -53,22 +53,24 @@ func main() { var logSys *log.Logger flags := log.LstdFlags - if LogFile != "" { - logfile, err := os.OpenFile(LogFile, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) - if err != nil { - panic(fmt.Sprintf("error opening log file '%s': %v", LogFile, err)) - } - defer logfile.Close() - log.SetOutput(logfile) - logSys = log.New(logfile, "", flags) - } else { - logSys = log.New(os.Stdout, "", flags) - } ethutil.ReadConfig(DataDir) logger := ethutil.Config.Log - logger.AddLogSystem(logSys) - ethchain.InitFees() + if LogFile != "" { + logfile, err := os.OpenFile(LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + panic(fmt.Sprintf("error opening log file '%s': %v", LogFile, err)) + } + defer logfile.Close() + log.SetOutput(logfile) + logSys = log.New(logfile, "", flags) + logger.AddLogSystem(logSys) + } + /*else { + logSys = log.New(os.Stdout, "", flags) + }*/ + + ethchain.InitFees() ethutil.Config.Seed = UseSeed // Instantiated a eth stack @@ -101,9 +103,6 @@ func main() { } } os.Exit(0) - case len(ImportKey) == 0: - utils.CreateKeyPair(false) - fallthrough case ExportKey: key := ethutil.Config.Db.GetKeys()[0] logSys.Println(fmt.Sprintf("prvk: %x\n", key.PrivateKey)) @@ -111,6 +110,9 @@ func main() { case ShowGenesis: logSys.Println(ethereum.BlockChain().Genesis()) os.Exit(0) + default: + // Creates a keypair if non exists + utils.CreateKeyPair(false) } // client