Leverage the new watch & address:changed functionality

This commit is contained in:
obscuren 2014-04-26 01:47:04 +02:00
parent d0438ac10a
commit e16fd323e8
8 changed files with 115 additions and 69 deletions

View File

@ -47,6 +47,10 @@ window.eth = {
postData({call: "getKey"}, cb); postData({call: "getKey"}, cb);
}, },
watch: function(address) {
postData({call: "watch", args: [address]});
},
on: function(event, cb) { on: function(event, cb) {
if(eth._onCallbacks[event] === undefined) { if(eth._onCallbacks[event] === undefined) {

View File

@ -74,14 +74,24 @@ ApplicationWindow {
var keys = eth.getKey() var keys = eth.getKey()
postData(data._seed, keys) postData(data._seed, keys)
break break
case "watch":
if(data.args.length > 0) {
eth.watch(data.args[0]);
}
} }
} }
function postData(seed, data) { function postData(seed, data) {
webview.experimental.postMessage(JSON.stringify({data: data, _seed: seed})) 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) { function onNewBlockCb(block) {
webview.experimental.postMessage(JSON.stringify({data: block, _event: "block:new"})) postEvent("block:new", block)
}
function onObjectChangeCb(stateObject) {
postEvent("object:change", stateObject)
} }
} }

View File

@ -22,12 +22,15 @@ function tests() {
} }
function init() { function init() {
eth.watch(jefcoinAddr);
eth.getKey(function(key) { eth.getKey(function(key) {
eth.getStorage(jefcoinAddr, key, function(storage) { eth.getStorage(jefcoinAddr, key, function(storage) {
document.querySelector("#currentAmount").innerHTML = "Amount: " + 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) { eth.getStorage(jefcoinAddr, key, function(storage) {
document.querySelector("#currentAmount").innerHTML = "Amount: " + storage; document.querySelector("#currentAmount").innerHTML = "Amount: " + storage;
}); });

View File

@ -2,7 +2,6 @@ package ethui
import ( import (
"bytes" "bytes"
"encoding/hex"
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
@ -13,45 +12,6 @@ import (
"strings" "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 { type Gui struct {
// The main application window // The main application window
win *qml.Window win *qml.Window
@ -96,9 +56,9 @@ func (ui *Gui) Start(assetPath string) {
// Register ethereum functions // Register ethereum functions
qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ 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")) ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.1"))
@ -169,13 +129,13 @@ func (ui *Gui) readPreviousTransactions() {
for it.Next() { for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value()) tx := ethchain.NewTransactionFromBytes(it.Value())
ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) ui.win.Root().Call("addTx", NewQTx(tx))
} }
it.Release() it.Release()
} }
func (ui *Gui) ProcessBlock(block *ethchain.Block) { 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 // 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 txMsg.Type == ethchain.TxPre {
if bytes.Compare(tx.Sender(), ui.addr) == 0 { 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.txDb.Put(tx.Hash(), tx.RlpEncode())
ui.eth.StateManager().GetAddrState(ui.addr).Nonce += 1 ui.eth.StateManager().GetAddrState(ui.addr).Nonce += 1
unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
} else if bytes.Compare(tx.Recipient, ui.addr) == 0 { } 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()) ui.txDb.Put(tx.Hash(), tx.RlpEncode())
unconfirmedFunds.Add(unconfirmedFunds, tx.Value) unconfirmedFunds.Add(unconfirmedFunds, tx.Value)

View File

@ -67,6 +67,10 @@ func (lib *EthLib) GetStateObject(address string) *Contract {
return NewContract(stateObject) 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) { func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) {
var hash []byte var hash []byte
var contractCreation bool var contractCreation bool
@ -117,7 +121,7 @@ func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, dataStr st
return ethutil.Hex(tx.Hash()), nil 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) hash, err := hex.DecodeString(hexHash)
if err != nil { if err != nil {
return nil return nil
@ -125,5 +129,5 @@ func (lib *EthLib) GetBlock(hexHash string) *Block {
block := lib.blockChain.GetBlock(hash) 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())}
} }

56
ethereal/ui/types.go Normal file
View File

@ -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)}
}

View File

@ -69,8 +69,10 @@ func (ui *UiLib) OpenHtml(path string) {
} }
win.Set("url", path) win.Set("url", path)
webView := win.ObjectByName("webView")
go func() { go func() {
blockChan := make(chan ethutil.React, 1) blockChan := make(chan ethutil.React, 1)
addrChan := make(chan ethutil.React, 1)
quitChan := make(chan bool) quitChan := make(chan bool)
go func() { go func() {
@ -82,8 +84,12 @@ func (ui *UiLib) OpenHtml(path string) {
break out break out
case block := <-blockChan: case block := <-blockChan:
if block, ok := block.Resource.(*ethchain.Block); ok { if block, ok := block.Resource.(*ethchain.Block); ok {
b := &Block{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} b := &QBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())}
win.ObjectByName("webView").Call("onNewBlockCb", b) 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) close(quitChan)
}() }()
ui.eth.Reactor().Subscribe("newBlock", blockChan) ui.eth.Reactor().Subscribe("newBlock", blockChan)
ui.eth.Reactor().Subscribe("addressChanged", addrChan)
win.Show() win.Show()
win.Wait() 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)) callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr), ethutil.Big(valueStr))
block := ui.eth.BlockChain().CurrentBlock block := ui.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, ethchain.RuntimeVars{ vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{
Origin: account.Address(), Origin: account.Address(),
BlockNumber: block.BlockInfo().Number, BlockNumber: block.BlockInfo().Number,
PrevHash: block.PrevHash, PrevHash: block.PrevHash,

View File

@ -53,6 +53,9 @@ func main() {
var logSys *log.Logger var logSys *log.Logger
flags := log.LstdFlags flags := log.LstdFlags
ethutil.ReadConfig(DataDir)
logger := ethutil.Config.Log
if LogFile != "" { if LogFile != "" {
logfile, err := os.OpenFile(LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) logfile, err := os.OpenFile(LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil { if err != nil {
@ -61,12 +64,11 @@ func main() {
defer logfile.Close() defer logfile.Close()
log.SetOutput(logfile) log.SetOutput(logfile)
logSys = log.New(logfile, "", flags) logSys = log.New(logfile, "", flags)
} else {
logSys = log.New(os.Stdout, "", flags)
}
ethutil.ReadConfig(DataDir)
logger := ethutil.Config.Log
logger.AddLogSystem(logSys) logger.AddLogSystem(logSys)
}
/*else {
logSys = log.New(os.Stdout, "", flags)
}*/
ethchain.InitFees() ethchain.InitFees()
ethutil.Config.Seed = UseSeed ethutil.Config.Seed = UseSeed
@ -101,9 +103,6 @@ func main() {
} }
} }
os.Exit(0) os.Exit(0)
case len(ImportKey) == 0:
utils.CreateKeyPair(false)
fallthrough
case ExportKey: case ExportKey:
key := ethutil.Config.Db.GetKeys()[0] key := ethutil.Config.Db.GetKeys()[0]
logSys.Println(fmt.Sprintf("prvk: %x\n", key.PrivateKey)) logSys.Println(fmt.Sprintf("prvk: %x\n", key.PrivateKey))
@ -111,6 +110,9 @@ func main() {
case ShowGenesis: case ShowGenesis:
logSys.Println(ethereum.BlockChain().Genesis()) logSys.Println(ethereum.BlockChain().Genesis())
os.Exit(0) os.Exit(0)
default:
// Creates a keypair if non exists
utils.CreateKeyPair(false)
} }
// client // client