diff --git a/ethereum/javascript_console.go b/ethereum/javascript_console.go index 9a10ca236..884b9a629 100644 --- a/ethereum/javascript_console.go +++ b/ethereum/javascript_console.go @@ -3,7 +3,9 @@ package main import ( "fmt" "github.com/ethereum/eth-go" + "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethpub" + "github.com/ethereum/eth-go/ethutil" "github.com/robertkrimen/otto" ) @@ -12,18 +14,83 @@ type Repl interface { } type JSRE struct { - vm *otto.Otto - lib *ethpub.PEthereum + ethereum *eth.Ethereum + vm *otto.Otto + lib *ethpub.PEthereum + + blockChan chan ethutil.React + changeChan chan ethutil.React + quitChan chan bool + + objectCb map[string][]otto.Value } func NewJSRE(ethereum *eth.Ethereum) *JSRE { - re := &JSRE{vm: otto.New(), lib: ethpub.NewPEthereum(ethereum)} + re := &JSRE{ + ethereum, + otto.New(), + ethpub.NewPEthereum(ethereum), + make(chan ethutil.React, 1), + make(chan ethutil.React, 1), + make(chan bool), + make(map[string][]otto.Value), + } + + // We have to make sure that, whoever calls this, calls "Stop" + go re.mainLoop() re.Bind("eth", &JSEthereum{re.lib, re.vm}) + t, _ := re.vm.Get("eth") + t.Object().Set("watch", func(call otto.FunctionCall) otto.Value { + addr, _ := call.Argument(0).ToString() + cb := call.Argument(1) + + re.objectCb[addr] = append(re.objectCb[addr], cb) + + event := "object:" + string(ethutil.FromHex(addr)) + ethereum.Reactor().Subscribe(event, re.changeChan) + + return otto.UndefinedValue() + }) return re } +func (self *JSRE) Stop() { + // Kill the main loop + self.quitChan <- true + + close(self.blockChan) + close(self.quitChan) + close(self.changeChan) +} + +func (self *JSRE) mainLoop() { + // Subscribe to events + reactor := self.ethereum.Reactor() + reactor.Subscribe("newBlock", self.blockChan) + +out: + for { + select { + case <-self.quitChan: + break out + case block := <-self.blockChan: + if _, ok := block.Resource.(*ethchain.Block); ok { + } + case object := <-self.changeChan: + if stateObject, ok := object.Resource.(*ethchain.StateObject); ok { + for _, cb := range self.objectCb[ethutil.Hex(stateObject.Address())] { + val, _ := self.vm.ToValue(ethpub.NewPStateObject(stateObject)) + cb.Call(cb, val) + } + } else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok { + fmt.Println(storageObject) + } + } + } +} + func (self *JSRE) Bind(name string, v interface{}) { self.vm.Set(name, v) } @@ -99,7 +166,6 @@ func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, initStr, body return self.toVal(r) } -// Wrapper function func (self *JSEthereum) toVal(v interface{}) otto.Value { result, err := self.vm.ToValue(v)