Merge remote-tracking branch 'ethereum/conversion' into conversion
This commit is contained in:
259
cmd/ethereum/admin.go
Normal file
259
cmd/ethereum/admin.go
Normal file
@ -0,0 +1,259 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
"github.com/obscuren/otto"
|
||||
)
|
||||
|
||||
/*
|
||||
node admin bindings
|
||||
*/
|
||||
|
||||
func (js *jsre) adminBindings() {
|
||||
js.re.Set("admin", struct{}{})
|
||||
t, _ := js.re.Get("admin")
|
||||
admin := t.Object()
|
||||
admin.Set("suggestPeer", js.suggestPeer)
|
||||
admin.Set("startRPC", js.startRPC)
|
||||
admin.Set("startMining", js.startMining)
|
||||
admin.Set("stopMining", js.stopMining)
|
||||
admin.Set("nodeInfo", js.nodeInfo)
|
||||
admin.Set("peers", js.peers)
|
||||
admin.Set("newAccount", js.newAccount)
|
||||
admin.Set("unlock", js.unlock)
|
||||
admin.Set("import", js.importChain)
|
||||
admin.Set("export", js.exportChain)
|
||||
admin.Set("dumpBlock", js.dumpBlock)
|
||||
}
|
||||
|
||||
func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
|
||||
_, err := call.Argument(0).ToInteger()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
// threads now ignored
|
||||
err = js.ethereum.StartMining()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
|
||||
js.ethereum.StopMining()
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
|
||||
addr, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
port, err := call.Argument(1).ToInteger()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
dataDir := js.ethereum.DataDir
|
||||
|
||||
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
|
||||
if err != nil {
|
||||
fmt.Printf("Can't listen on %s:%d: %v", addr, port, err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
go http.Serve(l, rpc.JSONRPC(xeth.New(js.ethereum, nil), dataDir))
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) suggestPeer(call otto.FunctionCall) otto.Value {
|
||||
nodeURL, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
err = js.ethereum.SuggestPeer(nodeURL)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
|
||||
addr, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
seconds, err := call.Argument(2).ToInteger()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
arg := call.Argument(1)
|
||||
var passphrase string
|
||||
if arg.IsUndefined() {
|
||||
fmt.Println("Please enter a passphrase now.")
|
||||
passphrase, err = readPassword("Passphrase: ", true)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
} else {
|
||||
passphrase, err = arg.ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
}
|
||||
am := js.ethereum.AccountManager()
|
||||
// err := am.Unlock(common.FromHex(split[0]), split[1])
|
||||
// if err != nil {
|
||||
// utils.Fatalf("Unlock account failed '%v'", err)
|
||||
// }
|
||||
err = am.TimedUnlock(common.FromHex(addr), passphrase, time.Duration(seconds)*time.Second)
|
||||
if err != nil {
|
||||
fmt.Printf("Unlock account failed '%v'\n", err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
|
||||
arg := call.Argument(0)
|
||||
var passphrase string
|
||||
if arg.IsUndefined() {
|
||||
fmt.Println("The new account will be encrypted with a passphrase.")
|
||||
fmt.Println("Please enter a passphrase now.")
|
||||
auth, err := readPassword("Passphrase: ", true)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
confirm, err := readPassword("Repeat Passphrase: ", false)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
if auth != confirm {
|
||||
utils.Fatalf("Passphrases did not match.")
|
||||
}
|
||||
passphrase = auth
|
||||
} else {
|
||||
var err error
|
||||
passphrase, err = arg.ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
}
|
||||
acct, err := js.ethereum.AccountManager().NewAccount(passphrase)
|
||||
if err != nil {
|
||||
fmt.Printf("Could not create the account: %v", err)
|
||||
return otto.UndefinedValue()
|
||||
}
|
||||
return js.re.ToVal(common.Bytes2Hex(acct.Address))
|
||||
}
|
||||
|
||||
func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
|
||||
return js.re.ToVal(js.ethereum.NodeInfo())
|
||||
}
|
||||
|
||||
func (js *jsre) peers(call otto.FunctionCall) otto.Value {
|
||||
return js.re.ToVal(js.ethereum.PeersInfo())
|
||||
}
|
||||
|
||||
func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
|
||||
if len(call.ArgumentList) == 0 {
|
||||
fmt.Println("err: require file name")
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
fn, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
var fh *os.File
|
||||
fh, err = os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
defer fh.Close()
|
||||
|
||||
var blocks types.Blocks
|
||||
if err = rlp.Decode(fh, &blocks); err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
js.ethereum.ChainManager().Reset()
|
||||
if err = js.ethereum.ChainManager().InsertChain(blocks); err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
|
||||
if len(call.ArgumentList) == 0 {
|
||||
fmt.Println("err: require file name")
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
fn, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
data := js.ethereum.ChainManager().Export()
|
||||
if err := common.WriteFile(fn, data); err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
|
||||
var block *types.Block
|
||||
if len(call.ArgumentList) > 0 {
|
||||
if call.Argument(0).IsNumber() {
|
||||
num, _ := call.Argument(0).ToInteger()
|
||||
block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
|
||||
} else if call.Argument(0).IsString() {
|
||||
hash, _ := call.Argument(0).ToString()
|
||||
block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
|
||||
} else {
|
||||
fmt.Println("invalid argument for dump. Either hex string or number")
|
||||
}
|
||||
|
||||
} else {
|
||||
block = js.ethereum.ChainManager().CurrentBlock()
|
||||
}
|
||||
if block == nil {
|
||||
fmt.Println("block not found")
|
||||
return otto.UndefinedValue()
|
||||
}
|
||||
|
||||
statedb := state.New(block.Root(), js.ethereum.StateDb())
|
||||
dump := statedb.RawDump()
|
||||
return js.re.ToVal(dump)
|
||||
|
||||
}
|
@ -20,18 +20,16 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/javascript"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
re "github.com/ethereum/go-ethereum/jsre"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
"github.com/obscuren/otto"
|
||||
"github.com/peterh/liner"
|
||||
)
|
||||
|
||||
@ -59,7 +57,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
|
||||
func (r dumbterm) AppendHistory(string) {}
|
||||
|
||||
type jsre struct {
|
||||
re *javascript.JSRE
|
||||
re *re.JSRE
|
||||
ethereum *eth.Ethereum
|
||||
xeth *xeth.XEth
|
||||
ps1 string
|
||||
@ -68,11 +66,12 @@ type jsre struct {
|
||||
prompter
|
||||
}
|
||||
|
||||
func newJSRE(ethereum *eth.Ethereum) *jsre {
|
||||
func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
|
||||
js := &jsre{ethereum: ethereum, ps1: "> "}
|
||||
js.xeth = xeth.New(ethereum, js)
|
||||
js.re = javascript.NewJSRE(js.xeth)
|
||||
js.initStdFuncs()
|
||||
js.re = re.New(libPath)
|
||||
js.apiBindings()
|
||||
js.adminBindings()
|
||||
|
||||
if !liner.TerminalSupported() {
|
||||
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
||||
@ -89,6 +88,49 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
|
||||
return js
|
||||
}
|
||||
|
||||
func (js *jsre) apiBindings() {
|
||||
|
||||
ethApi := rpc.NewEthereumApi(js.xeth, js.ethereum.DataDir)
|
||||
js.re.Bind("jeth", rpc.NewJeth(ethApi, js.re.ToVal))
|
||||
|
||||
_, err := js.re.Eval(re.BigNumber_JS)
|
||||
|
||||
if err != nil {
|
||||
utils.Fatalf("Error loading bignumber.js: %v", err)
|
||||
}
|
||||
|
||||
// we need to declare a dummy setTimeout. Otto does not support it
|
||||
_, err = js.re.Eval("setTimeout = function(cb, delay) {};")
|
||||
if err != nil {
|
||||
utils.Fatalf("Error defining setTimeout: %v", err)
|
||||
}
|
||||
|
||||
_, err = js.re.Eval(re.Ethereum_JS)
|
||||
if err != nil {
|
||||
utils.Fatalf("Error loading ethereum.js: %v", err)
|
||||
}
|
||||
|
||||
_, err = js.re.Eval("var web3 = require('web3');")
|
||||
if err != nil {
|
||||
utils.Fatalf("Error requiring web3: %v", err)
|
||||
}
|
||||
|
||||
_, err = js.re.Eval("web3.setProvider(jeth)")
|
||||
if err != nil {
|
||||
utils.Fatalf("Error setting web3 provider: %v", err)
|
||||
}
|
||||
_, err = js.re.Eval(`
|
||||
var eth = web3.eth;
|
||||
var shh = web3.shh;
|
||||
var db = web3.db;
|
||||
var net = web3.net;
|
||||
`)
|
||||
if err != nil {
|
||||
utils.Fatalf("Error setting namespaces: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
|
||||
p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
|
||||
answer, _ := self.Prompt(p)
|
||||
@ -111,15 +153,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
|
||||
}
|
||||
|
||||
func (self *jsre) exec(filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := self.re.Run(string(content)); err != nil {
|
||||
if err := self.re.Exec(filename); err != nil {
|
||||
return fmt.Errorf("Javascript Error: %v", err)
|
||||
}
|
||||
return nil
|
||||
@ -193,102 +227,8 @@ func (self *jsre) setIndent() {
|
||||
}
|
||||
|
||||
func (self *jsre) printValue(v interface{}) {
|
||||
method, _ := self.re.Vm.Get("prettyPrint")
|
||||
v, err := self.re.Vm.ToValue(v)
|
||||
val, err := self.re.PrettyPrint(v)
|
||||
if err == nil {
|
||||
val, err := method.Call(method, v)
|
||||
if err == nil {
|
||||
fmt.Printf("%v", val)
|
||||
}
|
||||
fmt.Printf("%v", val)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *jsre) initStdFuncs() {
|
||||
t, _ := self.re.Vm.Get("eth")
|
||||
eth := t.Object()
|
||||
eth.Set("connect", self.connect)
|
||||
eth.Set("stopMining", self.stopMining)
|
||||
eth.Set("startMining", self.startMining)
|
||||
eth.Set("dump", self.dump)
|
||||
eth.Set("export", self.export)
|
||||
}
|
||||
|
||||
/*
|
||||
* The following methods are natively implemented javascript functions.
|
||||
*/
|
||||
|
||||
func (self *jsre) dump(call otto.FunctionCall) otto.Value {
|
||||
var block *types.Block
|
||||
|
||||
if len(call.ArgumentList) > 0 {
|
||||
if call.Argument(0).IsNumber() {
|
||||
num, _ := call.Argument(0).ToInteger()
|
||||
block = self.ethereum.ChainManager().GetBlockByNumber(uint64(num))
|
||||
} else if call.Argument(0).IsString() {
|
||||
hash, _ := call.Argument(0).ToString()
|
||||
block = self.ethereum.ChainManager().GetBlock(common.Hex2Bytes(hash))
|
||||
} else {
|
||||
fmt.Println("invalid argument for dump. Either hex string or number")
|
||||
}
|
||||
|
||||
if block == nil {
|
||||
fmt.Println("block not found")
|
||||
|
||||
return otto.UndefinedValue()
|
||||
}
|
||||
|
||||
} else {
|
||||
block = self.ethereum.ChainManager().CurrentBlock()
|
||||
}
|
||||
|
||||
statedb := state.New(block.Root(), self.ethereum.StateDb())
|
||||
|
||||
v, _ := self.re.Vm.ToValue(statedb.RawDump())
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (self *jsre) stopMining(call otto.FunctionCall) otto.Value {
|
||||
self.ethereum.StopMining()
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *jsre) startMining(call otto.FunctionCall) otto.Value {
|
||||
if err := self.ethereum.StartMining(); err != nil {
|
||||
return otto.FalseValue()
|
||||
}
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *jsre) connect(call otto.FunctionCall) otto.Value {
|
||||
nodeURL, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
return otto.FalseValue()
|
||||
}
|
||||
if err := self.ethereum.SuggestPeer(nodeURL); err != nil {
|
||||
return otto.FalseValue()
|
||||
}
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *jsre) export(call otto.FunctionCall) otto.Value {
|
||||
if len(call.ArgumentList) == 0 {
|
||||
fmt.Println("err: require file name")
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
fn, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
data := self.ethereum.ChainManager().Export()
|
||||
|
||||
if err := common.WriteFile(fn, data); err != nil {
|
||||
fmt.Println(err)
|
||||
return otto.FalseValue()
|
||||
}
|
||||
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
252
cmd/ethereum/js_test.go
Normal file
252
cmd/ethereum/js_test.go
Normal file
@ -0,0 +1,252 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/obscuren/otto"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
)
|
||||
|
||||
var port = 30300
|
||||
|
||||
func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
|
||||
os.RemoveAll("/tmp/eth/")
|
||||
err = os.MkdirAll("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/", os.ModePerm)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll("/tmp/eth/data", os.ModePerm)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
// FIXME: this does not work ATM
|
||||
ks := crypto.NewKeyStorePlain("/tmp/eth/keys")
|
||||
common.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
|
||||
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`))
|
||||
|
||||
port++
|
||||
ethereum, err = eth.New(ð.Config{
|
||||
DataDir: "/tmp/eth",
|
||||
AccountManager: accounts.NewManager(ks),
|
||||
Port: fmt.Sprintf("%d", port),
|
||||
MaxPeers: 10,
|
||||
Name: "test",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
|
||||
repl = newJSRE(ethereum, assetPath)
|
||||
return
|
||||
}
|
||||
|
||||
func TestNodeInfo(t *testing.T) {
|
||||
repl, ethereum, err := testJEthRE(t)
|
||||
if err != nil {
|
||||
t.Errorf("error creating jsre, got %v", err)
|
||||
return
|
||||
}
|
||||
err = ethereum.Start()
|
||||
if err != nil {
|
||||
t.Errorf("error starting ethereum: %v", err)
|
||||
return
|
||||
}
|
||||
defer ethereum.Stop()
|
||||
|
||||
val, err := repl.re.Run("admin.nodeInfo()")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
exp, err := val.Export()
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
nodeInfo, ok := exp.(*eth.NodeInfo)
|
||||
if !ok {
|
||||
t.Errorf("expected nodeInfo, got %v", err)
|
||||
}
|
||||
exp = "test"
|
||||
got := nodeInfo.Name
|
||||
if exp != got {
|
||||
t.Errorf("expected %v, got %v", exp, got)
|
||||
}
|
||||
exp = 30301
|
||||
port := nodeInfo.DiscPort
|
||||
if exp != port {
|
||||
t.Errorf("expected %v, got %v", exp, port)
|
||||
}
|
||||
exp = 30301
|
||||
port = nodeInfo.TCPPort
|
||||
if exp != port {
|
||||
t.Errorf("expected %v, got %v", exp, port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccounts(t *testing.T) {
|
||||
repl, ethereum, err := testJEthRE(t)
|
||||
if err != nil {
|
||||
t.Errorf("error creating jsre, got %v", err)
|
||||
return
|
||||
}
|
||||
err = ethereum.Start()
|
||||
if err != nil {
|
||||
t.Errorf("error starting ethereum: %v", err)
|
||||
return
|
||||
}
|
||||
defer ethereum.Stop()
|
||||
|
||||
val, err := repl.re.Run("eth.coinbase")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
pp, err := repl.re.PrettyPrint(val)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
if !val.IsString() {
|
||||
t.Errorf("incorrect type, expected string, got %v: %v", val, pp)
|
||||
}
|
||||
strVal, _ := val.ToString()
|
||||
expected := "0xe273f01c99144c438695e10f24926dc1f9fbf62d"
|
||||
if strVal != expected {
|
||||
t.Errorf("incorrect result, expected %s, got %v", expected, strVal)
|
||||
}
|
||||
|
||||
val, err = repl.re.Run(`admin.newAccount("password")`)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
addr, err := val.ToString()
|
||||
if err != nil {
|
||||
t.Errorf("expected string, got %v", err)
|
||||
}
|
||||
|
||||
val, err = repl.re.Run("eth.accounts")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
exp, err := val.Export()
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
addrs, ok := exp.([]string)
|
||||
if !ok {
|
||||
t.Errorf("expected []string, got %v", err)
|
||||
}
|
||||
if len(addrs) != 2 || (addr != addrs[0][2:] && addr != addrs[1][2:]) {
|
||||
t.Errorf("expected addrs == [<default>, <new>], got %v (%v)", addrs, addr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBlockChain(t *testing.T) {
|
||||
repl, ethereum, err := testJEthRE(t)
|
||||
if err != nil {
|
||||
t.Errorf("error creating jsre, got %v", err)
|
||||
return
|
||||
}
|
||||
err = ethereum.Start()
|
||||
if err != nil {
|
||||
t.Errorf("error starting ethereum: %v", err)
|
||||
return
|
||||
}
|
||||
defer ethereum.Stop()
|
||||
|
||||
// should get current block
|
||||
val0, err := repl.re.Run("admin.dumpBlock()")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
fn := "/tmp/eth/data/blockchain.0"
|
||||
_, err = repl.re.Run("admin.export(\"" + fn + "\")")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if _, err = os.Stat(fn); err != nil {
|
||||
t.Errorf("expected no error on file, got %v", err)
|
||||
}
|
||||
|
||||
_, err = repl.re.Run("admin.import(\"" + fn + "\")")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
var val1 otto.Value
|
||||
|
||||
// should get current block
|
||||
val1, err = repl.re.Run("admin.dumpBlock()")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
// FIXME: neither != , nor reflect.DeepEqual works, doing string comparison
|
||||
v0 := fmt.Sprintf("%v", val0)
|
||||
v1 := fmt.Sprintf("%v", val1)
|
||||
if v0 != v1 {
|
||||
t.Errorf("expected same head after export-import, got %v (!=%v)", v1, v0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMining(t *testing.T) {
|
||||
repl, ethereum, err := testJEthRE(t)
|
||||
if err != nil {
|
||||
t.Errorf("error creating jsre, got %v", err)
|
||||
return
|
||||
}
|
||||
err = ethereum.Start()
|
||||
if err != nil {
|
||||
t.Errorf("error starting ethereum: %v", err)
|
||||
return
|
||||
}
|
||||
defer ethereum.Stop()
|
||||
|
||||
val, err := repl.re.Run("eth.mining")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
var mining bool
|
||||
mining, err = val.ToBoolean()
|
||||
if err != nil {
|
||||
t.Errorf("expected boolean, got %v", err)
|
||||
}
|
||||
if mining {
|
||||
t.Errorf("expected false (not mining), got true")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRPC(t *testing.T) {
|
||||
repl, ethereum, err := testJEthRE(t)
|
||||
if err != nil {
|
||||
t.Errorf("error creating jsre, got %v", err)
|
||||
return
|
||||
}
|
||||
err = ethereum.Start()
|
||||
if err != nil {
|
||||
t.Errorf("error starting ethereum: %v", err)
|
||||
return
|
||||
}
|
||||
defer ethereum.Stop()
|
||||
|
||||
val, err := repl.re.Run(`admin.startRPC("127.0.0.1", 5004)`)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
success, _ := val.ToBoolean()
|
||||
if !success {
|
||||
t.Errorf("expected true (started), got false")
|
||||
}
|
||||
}
|
@ -31,9 +31,9 @@ import (
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
"github.com/peterh/liner"
|
||||
@ -41,7 +41,7 @@ import (
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Ethereum(G)"
|
||||
Version = "0.9.0"
|
||||
Version = "0.9.1"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -89,16 +89,20 @@ Use "ethereum dump 0" to dump the genesis block.
|
||||
`,
|
||||
},
|
||||
{
|
||||
Action: runjs,
|
||||
Name: "js",
|
||||
Usage: `interactive JavaScript console`,
|
||||
Action: console,
|
||||
Name: "console",
|
||||
Usage: `Ethereum Console: interactive JavaScript environment`,
|
||||
Description: `
|
||||
In the console, you can use the eth object to interact
|
||||
with the running ethereum stack. The API does not match
|
||||
ethereum.js.
|
||||
|
||||
A JavaScript file can be provided as the argument. The
|
||||
runtime will execute the file and exit.
|
||||
Console is an interactive shell for the Ethereum JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
|
||||
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
||||
`,
|
||||
},
|
||||
{
|
||||
Action: execJSFiles,
|
||||
Name: "js",
|
||||
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
|
||||
Description: `
|
||||
The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
||||
`,
|
||||
},
|
||||
{
|
||||
@ -116,6 +120,7 @@ runtime will execute the file and exit.
|
||||
utils.UnlockedAccountFlag,
|
||||
utils.BootnodesFlag,
|
||||
utils.DataDirFlag,
|
||||
utils.JSpathFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.LogFileFlag,
|
||||
utils.LogFormatFlag,
|
||||
@ -131,6 +136,7 @@ runtime will execute the file and exit.
|
||||
utils.RPCPortFlag,
|
||||
utils.UnencryptedKeysFlag,
|
||||
utils.VMDebugFlag,
|
||||
|
||||
//utils.VMTypeFlag,
|
||||
}
|
||||
|
||||
@ -168,7 +174,7 @@ func run(ctx *cli.Context) {
|
||||
ethereum.WaitForShutdown()
|
||||
}
|
||||
|
||||
func runjs(ctx *cli.Context) {
|
||||
func console(ctx *cli.Context) {
|
||||
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
||||
ethereum, err := eth.New(cfg)
|
||||
if err != nil {
|
||||
@ -176,14 +182,26 @@ func runjs(ctx *cli.Context) {
|
||||
}
|
||||
|
||||
startEth(ctx, ethereum)
|
||||
repl := newJSRE(ethereum)
|
||||
if len(ctx.Args()) == 0 {
|
||||
repl.interactive()
|
||||
} else {
|
||||
for _, file := range ctx.Args() {
|
||||
repl.exec(file)
|
||||
}
|
||||
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
||||
repl.interactive()
|
||||
|
||||
ethereum.Stop()
|
||||
ethereum.WaitForShutdown()
|
||||
}
|
||||
|
||||
func execJSFiles(ctx *cli.Context) {
|
||||
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
||||
ethereum, err := eth.New(cfg)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
startEth(ctx, ethereum)
|
||||
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
||||
for _, file := range ctx.Args() {
|
||||
repl.exec(file)
|
||||
}
|
||||
|
||||
ethereum.Stop()
|
||||
ethereum.WaitForShutdown()
|
||||
}
|
||||
@ -284,7 +302,7 @@ func dump(ctx *cli.Context) {
|
||||
for _, arg := range ctx.Args() {
|
||||
var block *types.Block
|
||||
if hashish(arg) {
|
||||
block = chainmgr.GetBlock(common.Hex2Bytes(arg))
|
||||
block = chainmgr.GetBlock(common.HexToHash(arg))
|
||||
} else {
|
||||
num, _ := strconv.Atoi(arg)
|
||||
block = chainmgr.GetBlockByNumber(uint64(num))
|
||||
|
6
cmd/mist/assets/ext/bignumber.min.js
vendored
6
cmd/mist/assets/ext/bignumber.min.js
vendored
File diff suppressed because one or more lines are too long
@ -12,7 +12,7 @@ import "../ext/http.js" as Http
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
|
||||
|
||||
//flags: Qt.FramelessWindowHint
|
||||
// Use this to make the window frameless. But then you'll need to do move and resize by hand
|
||||
|
||||
@ -53,7 +53,7 @@ ApplicationWindow {
|
||||
whisperTab.view.url = "http://ethereum-dapp-whisper-client.meteor.com/";
|
||||
whisperTab.menuItem.title = "Whisper Chat";
|
||||
*/
|
||||
addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"});
|
||||
addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"});
|
||||
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
|
||||
addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"});
|
||||
addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
|
||||
@ -126,7 +126,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function newBrowserTab(url) {
|
||||
|
||||
|
||||
var urlMatches = url.toString().match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
|
||||
var requestedDomain = urlMatches && urlMatches[1];
|
||||
|
||||
@ -138,17 +138,17 @@ ApplicationWindow {
|
||||
var existingDomain = matches && matches[1];
|
||||
if (requestedDomain == existingDomain) {
|
||||
domainAlreadyOpen = true;
|
||||
|
||||
|
||||
if (mainSplit.views[i].view.url != url){
|
||||
mainSplit.views[i].view.url = url;
|
||||
}
|
||||
|
||||
|
||||
activeView(mainSplit.views[i].view, mainSplit.views[i].menuItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!domainAlreadyOpen) {
|
||||
if (!domainAlreadyOpen) {
|
||||
var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true});
|
||||
window.view.url = url;
|
||||
window.menuItem.title = "Mist";
|
||||
@ -157,7 +157,6 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu {
|
||||
title: "File"
|
||||
@ -165,7 +164,7 @@ ApplicationWindow {
|
||||
text: "New tab"
|
||||
shortcut: "Ctrl+t"
|
||||
onTriggered: {
|
||||
activeView(catalog.view, catalog.menuItem);
|
||||
activeView(catalog.view, catalog.menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,15 +205,6 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Run JS file"
|
||||
onTriggered: {
|
||||
generalFileDialog.show(true, function(path) {
|
||||
eth.evalJavascriptFile(path)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Dump state"
|
||||
onTriggered: {
|
||||
@ -313,28 +303,28 @@ ApplicationWindow {
|
||||
Layout.minimumWidth: 192
|
||||
Layout.maximumWidth: 192
|
||||
|
||||
FontLoader {
|
||||
FontLoader {
|
||||
id: sourceSansPro
|
||||
source: "fonts/SourceSansPro-Regular.ttf"
|
||||
source: "fonts/SourceSansPro-Regular.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Semibold.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Bold.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Black.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Light.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-ExtraLight.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Semibold.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Bold.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Black.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-Light.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
source: "fonts/SourceSansPro-ExtraLight.ttf"
|
||||
}
|
||||
FontLoader {
|
||||
id: simpleLineIcons
|
||||
source: "fonts/Simple-Line-Icons.ttf"
|
||||
source: "fonts/Simple-Line-Icons.ttf"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -393,7 +383,7 @@ ApplicationWindow {
|
||||
|
||||
function setSelection(on) {
|
||||
sel.visible = on
|
||||
|
||||
|
||||
if (this.closable == true) {
|
||||
closeIcon.visible = on
|
||||
}
|
||||
@ -404,7 +394,7 @@ ApplicationWindow {
|
||||
label.visible = !on
|
||||
buttonLabel.visible = on
|
||||
}
|
||||
|
||||
|
||||
width: 192
|
||||
height: 55
|
||||
color: "#00000000"
|
||||
@ -417,7 +407,7 @@ ApplicationWindow {
|
||||
Rectangle {
|
||||
// New App Button
|
||||
id: newAppButton
|
||||
visible: false
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 8
|
||||
border.width: 0
|
||||
@ -504,16 +494,16 @@ ApplicationWindow {
|
||||
id: buttonLabel
|
||||
visible: false
|
||||
text: "GO TO NEW APP"
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.DemiBold
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "#AAA0A0"
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.DemiBold
|
||||
elide: Text.ElideRight
|
||||
x:250
|
||||
@ -529,15 +519,15 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
id: secondary
|
||||
//only shows secondary title if there's no badge
|
||||
visible: (badgeContent == "icon" || badgeContent == "number" )? false : true
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.Light
|
||||
anchors {
|
||||
left: icon.right
|
||||
@ -566,8 +556,8 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
Text {
|
||||
|
||||
font.family: simpleLineIcons.name
|
||||
|
||||
font.family: simpleLineIcons.name
|
||||
anchors {
|
||||
centerIn: parent
|
||||
}
|
||||
@ -575,11 +565,11 @@ ApplicationWindow {
|
||||
font.pixelSize: 20
|
||||
text: "\ue082"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: badge
|
||||
visible: (badgeContent == "icon" || badgeContent == "number" )? true : false
|
||||
visible: (badgeContent == "icon" || badgeContent == "number" )? true : false
|
||||
width: 32
|
||||
color: "#05000000"
|
||||
anchors {
|
||||
@ -588,11 +578,11 @@ ApplicationWindow {
|
||||
bottom: parent.bottom;
|
||||
rightMargin: 4;
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
id: badgeIconLabel
|
||||
visible: (badgeContent == "icon") ? true : false;
|
||||
font.family: simpleLineIcons.name
|
||||
font.family: simpleLineIcons.name
|
||||
anchors {
|
||||
centerIn: parent
|
||||
}
|
||||
@ -600,7 +590,7 @@ ApplicationWindow {
|
||||
color: "#AAA0A0"
|
||||
font.pixelSize: 20
|
||||
text: badgeIcon
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: badgeNumberLabel
|
||||
@ -609,14 +599,14 @@ ApplicationWindow {
|
||||
centerIn: parent
|
||||
}
|
||||
horizontalAlignment: Text.AlignCenter
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.Light
|
||||
color: "#AAA0A0"
|
||||
font.pixelSize: 18
|
||||
text: badgeNumber
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function closeApp() {
|
||||
@ -685,7 +675,7 @@ ApplicationWindow {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 3
|
||||
|
||||
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
@ -702,7 +692,7 @@ ApplicationWindow {
|
||||
color: "transparent"
|
||||
Text {
|
||||
text: "ETHEREUM"
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.Regular
|
||||
// anchors.top: 20
|
||||
// anchors.left: 16
|
||||
@ -711,10 +701,10 @@ ApplicationWindow {
|
||||
topMargin: 4
|
||||
fill: parent
|
||||
}
|
||||
// anchors.leftMargin: 16
|
||||
// anchors.topMargin: 16
|
||||
// anchors.leftMargin: 16
|
||||
// anchors.topMargin: 16
|
||||
// anchors.verticalCenterOffset: 50
|
||||
color: "#AAA0A0"
|
||||
color: "#AAA0A0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,7 +725,7 @@ ApplicationWindow {
|
||||
|
||||
Text {
|
||||
text: "APPS"
|
||||
font.family: sourceSansPro.name
|
||||
font.family: sourceSansPro.name
|
||||
font.weight: Font.Regular
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 16
|
||||
@ -775,7 +765,7 @@ ApplicationWindow {
|
||||
anchors.left: menu.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
color: "#00000000"
|
||||
color: "#00000000"
|
||||
|
||||
/*Rectangle {
|
||||
id: urlPane
|
||||
|
@ -25,9 +25,7 @@ import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"sort"
|
||||
@ -99,7 +97,7 @@ func NewWindow(ethereum *eth.Ethereum) *Gui {
|
||||
return gui
|
||||
}
|
||||
|
||||
func (gui *Gui) Start(assetPath string) {
|
||||
func (gui *Gui) Start(assetPath, libPath string) {
|
||||
defer gui.txDb.Close()
|
||||
|
||||
guilogger.Infoln("Starting GUI")
|
||||
@ -117,7 +115,7 @@ func (gui *Gui) Start(assetPath string) {
|
||||
// Create a new QML engine
|
||||
gui.engine = qml.NewEngine()
|
||||
context := gui.engine.Context()
|
||||
gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
|
||||
gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath, libPath)
|
||||
gui.whisper = qwhisper.New(gui.eth.Whisper())
|
||||
|
||||
// Expose the eth library and the ui library to QML
|
||||
@ -292,25 +290,6 @@ func (self *Gui) getObjectByName(objectName string) qml.Object {
|
||||
return self.win.Root().ObjectByName(objectName)
|
||||
}
|
||||
|
||||
func loadJavascriptAssets(gui *Gui) (jsfiles string) {
|
||||
for _, fn := range []string{"ext/q.js", "ext/eth.js/main.js", "ext/eth.js/qt.js", "ext/setup.js"} {
|
||||
f, err := os.Open(gui.uiLib.AssetPath(fn))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
jsfiles += string(content)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (gui *Gui) SendCommand(cmd ServEv) {
|
||||
gui.serviceEvents <- cmd
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ func init() {
|
||||
utils.NodeKeyFileFlag,
|
||||
utils.RPCListenAddrFlag,
|
||||
utils.RPCPortFlag,
|
||||
utils.JSpathFlag,
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +112,7 @@ func run(ctx *cli.Context) {
|
||||
gui := NewWindow(ethereum)
|
||||
utils.RegisterInterrupt(func(os.Signal) { gui.Stop() })
|
||||
// gui blocks the main thread
|
||||
gui.Start(ctx.GlobalString(assetPathFlag.Name))
|
||||
gui.Start(ctx.GlobalString(assetPathFlag.Name), ctx.GlobalString(utils.JSpathFlag.Name))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
@ -29,7 +28,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/event/filter"
|
||||
"github.com/ethereum/go-ethereum/javascript"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
"github.com/obscuren/qml"
|
||||
)
|
||||
@ -49,15 +47,19 @@ type UiLib struct {
|
||||
// The main application window
|
||||
win *qml.Window
|
||||
|
||||
jsEngine *javascript.JSRE
|
||||
|
||||
filterCallbacks map[int][]int
|
||||
filterManager *filter.FilterManager
|
||||
}
|
||||
|
||||
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
|
||||
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath, libPath string) *UiLib {
|
||||
x := xeth.New(eth, nil)
|
||||
lib := &UiLib{XEth: x, engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(x), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)}
|
||||
lib := &UiLib{
|
||||
XEth: x,
|
||||
engine: engine,
|
||||
eth: eth,
|
||||
assetPath: assetPath,
|
||||
filterCallbacks: make(map[int][]int),
|
||||
}
|
||||
lib.filterManager = filter.NewFilterManager(eth.EventMux())
|
||||
go lib.filterManager.Start()
|
||||
|
||||
@ -76,19 +78,6 @@ func (self *UiLib) ImportTx(rlpTx string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *UiLib) EvalJavascriptFile(path string) {
|
||||
self.jsEngine.LoadExtFile(path[7:])
|
||||
}
|
||||
|
||||
func (self *UiLib) EvalJavascriptString(str string) string {
|
||||
value, err := self.jsEngine.Run(str)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", value)
|
||||
}
|
||||
|
||||
func (ui *UiLib) Muted(content string) {
|
||||
component, err := ui.engine.LoadFile(ui.AssetPath("qml/muted.qml"))
|
||||
if err != nil {
|
||||
|
@ -163,6 +163,11 @@ var (
|
||||
Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
|
||||
Value: "any",
|
||||
}
|
||||
JSpathFlag = cli.StringFlag{
|
||||
Name: "jspath",
|
||||
Usage: "JS library path to be used with console and js subcommands",
|
||||
Value: ".",
|
||||
}
|
||||
)
|
||||
|
||||
func GetNAT(ctx *cli.Context) nat.Interface {
|
||||
|
Reference in New Issue
Block a user