From cb7f2d43b6da260dff80e4b705271c7088112c34 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Mon, 8 Jun 2015 19:14:42 +0200
Subject: added console binary

---
 cmd/console/admin.go     |   9 ++
 cmd/console/console      | Bin 0 -> 19332472 bytes
 cmd/console/contracts.go |   6 +
 cmd/console/history      |   7 ++
 cmd/console/js.go        | 279 +++++++++++++++++++++++++++++++++++++++++++++++
 cmd/console/main.go      | 101 +++++++++++++++++
 6 files changed, 402 insertions(+)
 create mode 100644 cmd/console/admin.go
 create mode 100755 cmd/console/console
 create mode 100644 cmd/console/contracts.go
 create mode 100755 cmd/console/history
 create mode 100644 cmd/console/js.go
 create mode 100644 cmd/console/main.go

(limited to 'cmd/console')

diff --git a/cmd/console/admin.go b/cmd/console/admin.go
new file mode 100644
index 000000000..dee88e3a0
--- /dev/null
+++ b/cmd/console/admin.go
@@ -0,0 +1,9 @@
+package main
+
+/*
+node admin bindings
+*/
+
+func (js *jsre) adminBindings() {
+
+}
diff --git a/cmd/console/console b/cmd/console/console
new file mode 100755
index 000000000..113fb5dac
Binary files /dev/null and b/cmd/console/console differ
diff --git a/cmd/console/contracts.go b/cmd/console/contracts.go
new file mode 100644
index 000000000..1f27838d1
--- /dev/null
+++ b/cmd/console/contracts.go
@@ -0,0 +1,6 @@
+package main
+
+var (
+	globalRegistrar     = `var GlobalRegistrar = web3.eth.contract([{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}]);`
+	globalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
+)
diff --git a/cmd/console/history b/cmd/console/history
new file mode 100755
index 000000000..728b6994a
--- /dev/null
+++ b/cmd/console/history
@@ -0,0 +1,7 @@
+eth.accounts
+help
+eth
+eth.getBlock(21)
+net
+admin
+eth
diff --git a/cmd/console/js.go b/cmd/console/js.go
new file mode 100644
index 000000000..8b9137add
--- /dev/null
+++ b/cmd/console/js.go
@@ -0,0 +1,279 @@
+// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301  USA
+
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"math/big"
+	"os"
+	"os/signal"
+	"path/filepath"
+	"strings"
+
+	"github.com/ethereum/go-ethereum/cmd/utils"
+	"github.com/ethereum/go-ethereum/common/docserver"
+	re "github.com/ethereum/go-ethereum/jsre"
+	"github.com/ethereum/go-ethereum/rpc"
+	"github.com/peterh/liner"
+	"github.com/robertkrimen/otto"
+)
+
+type prompter interface {
+	AppendHistory(string)
+	Prompt(p string) (string, error)
+	PasswordPrompt(p string) (string, error)
+}
+
+type dumbterm struct{ r *bufio.Reader }
+
+func (r dumbterm) Prompt(p string) (string, error) {
+	fmt.Print(p)
+	line, err := r.r.ReadString('\n')
+	return strings.TrimSuffix(line, "\n"), err
+}
+
+func (r dumbterm) PasswordPrompt(p string) (string, error) {
+	fmt.Println("!! Unsupported terminal, password will echo.")
+	fmt.Print(p)
+	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
+	fmt.Println()
+	return input, err
+}
+
+func (r dumbterm) AppendHistory(string) {}
+
+type jsre struct {
+	re      *re.JSRE
+	wait    chan *big.Int
+	ps1     string
+	atexit  func()
+	datadir string
+	prompter
+}
+
+func newJSRE(libPath, ipcpath string) *jsre {
+	js := &jsre{ps1: "> "}
+	js.wait = make(chan *big.Int)
+
+	// update state in separare forever blocks
+	js.re = re.New(libPath)
+	js.apiBindings(ipcpath)
+
+	if !liner.TerminalSupported() {
+		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
+	} else {
+		lr := liner.NewLiner()
+		js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
+		lr.SetCtrlCAborts(true)
+		js.prompter = lr
+		js.atexit = func() {
+			js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+			lr.Close()
+			close(js.wait)
+		}
+	}
+	return js
+}
+
+func (js *jsre) apiBindings(ipcpath string) {
+	ethApi := rpc.NewEthereumApi(nil)
+	jeth := rpc.NewJeth(ethApi, js.re, ipcpath)
+
+	js.re.Set("jeth", struct{}{})
+	t, _ := js.re.Get("jeth")
+	jethObj := t.Object()
+	jethObj.Set("send", jeth.SendIpc)
+	jethObj.Set("sendAsync", jeth.SendIpc)
+
+	err := js.re.Compile("bignumber.js", re.BigNumber_JS)
+	if err != nil {
+		utils.Fatalf("Error loading bignumber.js: %v", err)
+	}
+
+	err = js.re.Compile("ethereum.js", re.Web3_JS)
+	if err != nil {
+		utils.Fatalf("Error loading web3.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;
+  `)
+
+	if err != nil {
+		utils.Fatalf("Error setting namespaces: %v", err)
+	}
+
+	js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");")
+}
+
+var ds, _ = docserver.New("/")
+
+/*
+func (self *jsre) ConfirmTransaction(tx string) bool {
+	if self.ethereum.NatSpec {
+		notice := natspec.GetNotice(self.xeth, tx, ds)
+		fmt.Println(notice)
+		answer, _ := self.Prompt("Confirm Transaction [y/n]")
+		return strings.HasPrefix(strings.Trim(answer, " "), "y")
+	} else {
+		return true
+	}
+}
+
+func (self *jsre) UnlockAccount(addr []byte) bool {
+	fmt.Printf("Please unlock account %x.\n", addr)
+	pass, err := self.PasswordPrompt("Passphrase: ")
+	if err != nil {
+		return false
+	}
+	// TODO: allow retry
+	if err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil {
+		return false
+	} else {
+		fmt.Println("Account is now unlocked for this session.")
+		return true
+	}
+}
+*/
+
+func (self *jsre) exec(filename string) error {
+	if err := self.re.Exec(filename); err != nil {
+		self.re.Stop(false)
+		return fmt.Errorf("Javascript Error: %v", err)
+	}
+	self.re.Stop(true)
+	return nil
+}
+
+// show summary of current geth instance
+func (self *jsre) welcome() {
+	self.re.Eval(`
+		console.log('Connected to ' + web3.version.client);
+	`)
+}
+
+func (self *jsre) interactive() {
+	// Read input lines.
+	prompt := make(chan string)
+	inputln := make(chan string)
+	go func() {
+		defer close(inputln)
+		for {
+			line, err := self.Prompt(<-prompt)
+			if err != nil {
+				return
+			}
+			inputln <- line
+		}
+	}()
+	// Wait for Ctrl-C, too.
+	sig := make(chan os.Signal, 1)
+	signal.Notify(sig, os.Interrupt)
+
+	defer func() {
+		if self.atexit != nil {
+			self.atexit()
+		}
+		self.re.Stop(false)
+	}()
+	for {
+		prompt <- self.ps1
+		select {
+		case <-sig:
+			fmt.Println("caught interrupt, exiting")
+			return
+		case input, ok := <-inputln:
+			if !ok || indentCount <= 0 && input == "exit" {
+				return
+			}
+			if input == "" {
+				continue
+			}
+			str += input + "\n"
+			self.setIndent()
+			if indentCount <= 0 {
+				hist := str[:len(str)-1]
+				self.AppendHistory(hist)
+				self.parseInput(str)
+				str = ""
+			}
+		}
+	}
+}
+
+func (self *jsre) withHistory(op func(*os.File)) {
+	hist, err := os.OpenFile(filepath.Join(self.datadir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
+	if err != nil {
+		fmt.Printf("unable to open history file: %v\n", err)
+		return
+	}
+	op(hist)
+	hist.Close()
+}
+
+func (self *jsre) parseInput(code string) {
+	defer func() {
+		if r := recover(); r != nil {
+			fmt.Println("[native] error", r)
+		}
+	}()
+	value, err := self.re.Run(code)
+	if err != nil {
+		if ottoErr, ok := err.(*otto.Error); ok {
+			fmt.Println(ottoErr.String())
+		} else {
+			fmt.Println(err)
+		}
+		return
+	}
+	self.printValue(value)
+}
+
+var indentCount = 0
+var str = ""
+
+func (self *jsre) setIndent() {
+	open := strings.Count(str, "{")
+	open += strings.Count(str, "(")
+	closed := strings.Count(str, "}")
+	closed += strings.Count(str, ")")
+	indentCount = open - closed
+	if indentCount <= 0 {
+		self.ps1 = "> "
+	} else {
+		self.ps1 = strings.Join(make([]string, indentCount*2), "..")
+		self.ps1 += " "
+	}
+}
+
+func (self *jsre) printValue(v interface{}) {
+	val, err := self.re.PrettyPrint(v)
+	if err == nil {
+		fmt.Printf("%v", val)
+	}
+}
diff --git a/cmd/console/main.go b/cmd/console/main.go
new file mode 100644
index 000000000..781f1f8cb
--- /dev/null
+++ b/cmd/console/main.go
@@ -0,0 +1,101 @@
+/*
+	This file is part of go-ethereum
+
+	go-ethereum is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	go-ethereum is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @authors
+ * 	Jeffrey Wilcke <i@jev.io>
+ */
+package main
+
+import (
+	"fmt"
+	"io"
+	"os"
+
+	"github.com/mattn/go-colorable"
+	"github.com/mattn/go-isatty"
+	"github.com/codegangsta/cli"
+	"github.com/ethereum/go-ethereum/cmd/utils"
+	"github.com/ethereum/go-ethereum/logger"
+)
+
+const (
+	ClientIdentifier = "Geth console"
+	Version          = "0.9.27"
+)
+
+var (
+	gitCommit       string // set via linker flag
+	nodeNameVersion string
+	app           = utils.NewApp(Version, "the ether console")
+)
+
+func init() {
+	if gitCommit == "" {
+		nodeNameVersion = Version
+	} else {
+		nodeNameVersion = Version + "-" + gitCommit[:8]
+	}
+
+	app.Action = run
+	app.Flags = []cli.Flag{
+		utils.IPCDisabledFlag,
+		utils.IPCPathFlag,
+		utils.VerbosityFlag,
+		utils.JSpathFlag,
+	}
+
+	app.Before = func(ctx *cli.Context) error {
+		utils.SetupLogger(ctx)
+		return nil
+	}
+}
+
+func main() {
+	// Wrap the standard output with a colorified stream (windows)
+	if isatty.IsTerminal(os.Stdout.Fd()) {
+		if pr, pw, err := os.Pipe(); err == nil {
+			go io.Copy(colorable.NewColorableStdout(), pr)
+			os.Stdout = pw
+		}
+	}
+
+	var interrupted = false
+	utils.RegisterInterrupt(func(os.Signal) {
+		interrupted = true
+	})
+	utils.HandleInterrupt()
+
+	if err := app.Run(os.Args); err != nil {
+		fmt.Fprintln(os.Stderr, "Error: ", err)
+	}
+
+	// we need to run the interrupt callbacks in case gui is closed
+	// this skips if we got here by actual interrupt stopping the GUI
+	if !interrupted {
+		utils.RunInterruptCallbacks(os.Interrupt)
+	}
+	logger.Flush()
+}
+
+func run(ctx *cli.Context) {
+	jspath := ctx.GlobalString(utils.JSpathFlag.Name)
+	ipcpath := ctx.GlobalString(utils.IPCPathFlag.Name)
+
+	repl := newJSRE(jspath, ipcpath)
+	repl.welcome()
+	repl.interactive()
+}
-- 
cgit v1.2.3


From faab931ce1282dea50c8fdf0577c42ee67f69828 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Mon, 8 Jun 2015 19:51:38 +0200
Subject: only load supported api's

---
 cmd/console/js.go   | 82 +++++++++++++++++++++++++++++++++++++++++++++++++----
 cmd/console/main.go |  8 +++---
 2 files changed, 81 insertions(+), 9 deletions(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index 8b9137add..ea0961a39 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -26,12 +26,18 @@ import (
 	"path/filepath"
 	"strings"
 
+	"encoding/json"
+
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/common/docserver"
 	re "github.com/ethereum/go-ethereum/jsre"
 	"github.com/ethereum/go-ethereum/rpc"
+	"github.com/ethereum/go-ethereum/rpc/codec"
+	"github.com/ethereum/go-ethereum/rpc/comms"
+	"github.com/ethereum/go-ethereum/rpc/shared"
 	"github.com/peterh/liner"
 	"github.com/robertkrimen/otto"
+	"github.com/ethereum/go-ethereum/rpc/api"
 )
 
 type prompter interface {
@@ -120,9 +126,27 @@ func (js *jsre) apiBindings(ipcpath string) {
 	if err != nil {
 		utils.Fatalf("Error setting web3 provider: %v", err)
 	}
-	_, err = js.re.Eval(`
-var eth = web3.eth;
-  `)
+
+	apis, err := js.suportedApis(ipcpath)
+	if err != nil {
+		utils.Fatalf("Unable to determine supported api's: %v", err)
+	}
+
+	// load only supported API's in javascript runtime
+	shortcuts := "var eth = web3.eth; "
+	for _, apiName := range apis {
+		if apiName == api.Web3ApiName || apiName == api.EthApiName {
+			continue // manually mapped
+		}
+
+		if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil {
+			shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
+		} else {
+			utils.Fatalf("Error loading %s.js: %v", apiName, err)
+		}
+	}
+
+	_, err = js.re.Eval(shortcuts)
 
 	if err != nil {
 		utils.Fatalf("Error setting namespaces: %v", err)
@@ -170,11 +194,59 @@ func (self *jsre) exec(filename string) error {
 	return nil
 }
 
+func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
+	config := comms.IpcConfig{
+		Endpoint: ipcpath,
+	}
+
+	client, err := comms.NewIpcClient(config, codec.JSON)
+	if err != nil {
+		return nil, err
+	}
+
+	req := shared.Request{
+		Id:      1,
+		Jsonrpc: "2.0",
+		Method:  "support_apis",
+	}
+
+	err = client.Send(req)
+	if err != nil {
+		return nil, err
+	}
+
+	res, err := client.Recv()
+	if err != nil {
+		return nil, err
+	}
+
+	if sucRes, ok := res.(shared.SuccessResponse); ok {
+		data, _ := json.Marshal(sucRes.Result)
+		apis := make([]string, 0)
+		err = json.Unmarshal(data, &apis)
+		if err == nil {
+			return apis, nil
+		}
+	}
+
+	return nil, fmt.Errorf("Unable to determine supported API's")
+}
+
 // show summary of current geth instance
-func (self *jsre) welcome() {
+func (self *jsre) welcome(ipcpath string) {
 	self.re.Eval(`
-		console.log('Connected to ' + web3.version.client);
+		console.log('   Connected to: ' + web3.version.client);
 	`)
+
+	if apis, err := self.suportedApis(ipcpath); err == nil {
+		apisStr := ""
+		for _, api := range apis {
+			apisStr += api + " "
+		}
+		self.re.Eval(fmt.Sprintf(`console.log("Available api's: %s");`, apisStr))
+	} else {
+		utils.Fatalf("unable to determine supported api's - %v", err)
+	}
 }
 
 func (self *jsre) interactive() {
diff --git a/cmd/console/main.go b/cmd/console/main.go
index 781f1f8cb..9020a12fe 100644
--- a/cmd/console/main.go
+++ b/cmd/console/main.go
@@ -25,11 +25,11 @@ import (
 	"io"
 	"os"
 
-	"github.com/mattn/go-colorable"
-	"github.com/mattn/go-isatty"
 	"github.com/codegangsta/cli"
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/mattn/go-colorable"
+	"github.com/mattn/go-isatty"
 )
 
 const (
@@ -40,7 +40,7 @@ const (
 var (
 	gitCommit       string // set via linker flag
 	nodeNameVersion string
-	app           = utils.NewApp(Version, "the ether console")
+	app             = utils.NewApp(Version, "the ether console")
 )
 
 func init() {
@@ -96,6 +96,6 @@ func run(ctx *cli.Context) {
 	ipcpath := ctx.GlobalString(utils.IPCPathFlag.Name)
 
 	repl := newJSRE(jspath, ipcpath)
-	repl.welcome()
+	repl.welcome(ipcpath)
 	repl.interactive()
 }
-- 
cgit v1.2.3


From c6c443385b3e9998d3090785e4287e3836c70219 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Wed, 10 Jun 2015 10:24:22 +0200
Subject: changed console welcome message

---
 cmd/console/js.go | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index ea0961a39..4229a95a2 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -234,18 +234,15 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
 
 // show summary of current geth instance
 func (self *jsre) welcome(ipcpath string) {
-	self.re.Eval(`
-		console.log('   Connected to: ' + web3.version.client);
-	`)
-
-	if apis, err := self.suportedApis(ipcpath); err == nil {
-		apisStr := ""
-		for _, api := range apis {
-			apisStr += api + " "
-		}
-		self.re.Eval(fmt.Sprintf(`console.log("Available api's: %s");`, apisStr))
-	} else {
-		utils.Fatalf("unable to determine supported api's - %v", err)
+	self.re.Eval(`console.log('instance: ' + web3.version.client);`)
+	self.re.Eval(`console.log("coinbase: " + eth.coinbase);`)
+	self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`)
+	self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString()
+		+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
+
+	if modules, err := self.suportedApis(ipcpath); err == nil {
+		self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(modules, " ")))
+		self.re.Eval(`console.log(" modules: " + modules);`)
 	}
 }
 
-- 
cgit v1.2.3


From bd38428f33b127e9c60d26127695e50c55798fcd Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Wed, 10 Jun 2015 11:29:52 +0200
Subject: cleanup of javascript API

---
 cmd/console/js.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index 4229a95a2..76695cabd 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -32,12 +32,12 @@ import (
 	"github.com/ethereum/go-ethereum/common/docserver"
 	re "github.com/ethereum/go-ethereum/jsre"
 	"github.com/ethereum/go-ethereum/rpc"
+	"github.com/ethereum/go-ethereum/rpc/api"
 	"github.com/ethereum/go-ethereum/rpc/codec"
 	"github.com/ethereum/go-ethereum/rpc/comms"
 	"github.com/ethereum/go-ethereum/rpc/shared"
 	"github.com/peterh/liner"
 	"github.com/robertkrimen/otto"
-	"github.com/ethereum/go-ethereum/rpc/api"
 )
 
 type prompter interface {
@@ -235,6 +235,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
 // show summary of current geth instance
 func (self *jsre) welcome(ipcpath string) {
 	self.re.Eval(`console.log('instance: ' + web3.version.client);`)
+	self.re.Eval(`console.log(' datadir: ' + admin.datadir);`)
 	self.re.Eval(`console.log("coinbase: " + eth.coinbase);`)
 	self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`)
 	self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString()
-- 
cgit v1.2.3


From aa258dcc5f01a05c81075be999c83446862abb42 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Mon, 8 Jun 2015 19:14:42 +0200
Subject: added console binary

---
 cmd/console/js.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 89 insertions(+), 5 deletions(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index 76695cabd..633b79315 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -28,6 +28,8 @@ import (
 
 	"encoding/json"
 
+	"sort"
+
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/common/docserver"
 	re "github.com/ethereum/go-ethereum/jsre"
@@ -73,6 +75,79 @@ type jsre struct {
 	prompter
 }
 
+var (
+	loadedModulesMethods map[string][]string
+)
+
+func loadAutoCompletion(js *jsre, ipcpath string) {
+	modules, err := js.suportedApis(ipcpath)
+	if err != nil {
+		utils.Fatalf("Unable to determine supported modules - %v", err)
+	}
+
+	fmt.Printf("load autocompletion %v", modules)
+
+	loadedModulesMethods = make(map[string][]string)
+	for module, _ := range modules {
+		loadedModulesMethods[module] = api.AutoCompletion[module]
+	}
+}
+
+func keywordCompleter(line string) []string {
+	results := make([]string, 0)
+
+	if strings.Contains(line, ".") {
+		elements := strings.Split(line, ".")
+		if len(elements) == 2 {
+			module := elements[0]
+			partialMethod := elements[1]
+			if methods, found := loadedModulesMethods[module]; found {
+				for _, method := range methods {
+					if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
+						results = append(results, module+"."+method)
+					}
+				}
+			}
+		}
+	} else {
+		for module, methods := range loadedModulesMethods {
+			if line == module { // user typed in full module name, show all methods
+				for _, method := range methods {
+					results = append(results, module+"."+method)
+				}
+			} else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
+				results = append(results, module)
+			}
+		}
+	}
+	return results
+}
+
+func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) {
+	if len(line) == 0 {
+		return "", nil, ""
+	}
+
+	i := 0
+	for i = pos - 1; i > 0; i-- {
+		if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
+			continue
+		}
+		if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' {
+			continue
+		}
+		i += 1
+		break
+	}
+
+	begin := line[:i]
+	keyword := line[i:pos]
+	end := line[pos:]
+
+	completionWords := keywordCompleter(keyword)
+	return begin, completionWords, end
+}
+
 func newJSRE(libPath, ipcpath string) *jsre {
 	js := &jsre{ps1: "> "}
 	js.wait = make(chan *big.Int)
@@ -87,6 +162,9 @@ func newJSRE(libPath, ipcpath string) *jsre {
 		lr := liner.NewLiner()
 		js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
 		lr.SetCtrlCAborts(true)
+		loadAutoCompletion(js, ipcpath)
+		lr.SetWordCompleter(apiWordCompleter)
+		lr.SetTabCompletionStyle(liner.TabPrints)
 		js.prompter = lr
 		js.atexit = func() {
 			js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
@@ -134,7 +212,7 @@ func (js *jsre) apiBindings(ipcpath string) {
 
 	// load only supported API's in javascript runtime
 	shortcuts := "var eth = web3.eth; "
-	for _, apiName := range apis {
+	for apiName, _ := range apis {
 		if apiName == api.Web3ApiName || apiName == api.EthApiName {
 			continue // manually mapped
 		}
@@ -194,7 +272,7 @@ func (self *jsre) exec(filename string) error {
 	return nil
 }
 
-func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
+func (self *jsre) suportedApis(ipcpath string) (map[string]string, error) {
 	config := comms.IpcConfig{
 		Endpoint: ipcpath,
 	}
@@ -207,7 +285,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
 	req := shared.Request{
 		Id:      1,
 		Jsonrpc: "2.0",
-		Method:  "support_apis",
+		Method:  "modules",
 	}
 
 	err = client.Send(req)
@@ -222,7 +300,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) {
 
 	if sucRes, ok := res.(shared.SuccessResponse); ok {
 		data, _ := json.Marshal(sucRes.Result)
-		apis := make([]string, 0)
+		apis := make(map[string]string)
 		err = json.Unmarshal(data, &apis)
 		if err == nil {
 			return apis, nil
@@ -242,7 +320,13 @@ func (self *jsre) welcome(ipcpath string) {
 		+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
 
 	if modules, err := self.suportedApis(ipcpath); err == nil {
-		self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(modules, " ")))
+		loadedModules := make([]string, 0)
+		for api, version := range modules {
+			loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
+		}
+		sort.Strings(loadedModules)
+
+		self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " ")))
 		self.re.Eval(`console.log(" modules: " + modules);`)
 	}
 }
-- 
cgit v1.2.3


From ebaa9b9feb0325de33c69993cd9c215775618c7b Mon Sep 17 00:00:00 2001
From: Bas van Kervel <basvankervel@gmail.com>
Date: Thu, 11 Jun 2015 14:54:03 +0200
Subject: removed binary files

---
 cmd/console/console | Bin 19332472 -> 0 bytes
 cmd/console/history |   7 -------
 2 files changed, 7 deletions(-)
 delete mode 100755 cmd/console/console
 delete mode 100755 cmd/console/history

(limited to 'cmd/console')

diff --git a/cmd/console/console b/cmd/console/console
deleted file mode 100755
index 113fb5dac..000000000
Binary files a/cmd/console/console and /dev/null differ
diff --git a/cmd/console/history b/cmd/console/history
deleted file mode 100755
index 728b6994a..000000000
--- a/cmd/console/history
+++ /dev/null
@@ -1,7 +0,0 @@
-eth.accounts
-help
-eth
-eth.getBlock(21)
-net
-admin
-eth
-- 
cgit v1.2.3


From ec6a7b35f68d4fd0fbf8e59f70096765cff4bffc Mon Sep 17 00:00:00 2001
From: Bas van Kervel <basvankervel@gmail.com>
Date: Thu, 11 Jun 2015 15:00:33 +0200
Subject: removed obsolete print statement

---
 cmd/console/js.go | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index 633b79315..5aff8acfd 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -84,9 +84,7 @@ func loadAutoCompletion(js *jsre, ipcpath string) {
 	if err != nil {
 		utils.Fatalf("Unable to determine supported modules - %v", err)
 	}
-
-	fmt.Printf("load autocompletion %v", modules)
-
+	
 	loadedModulesMethods = make(map[string][]string)
 	for module, _ := range modules {
 		loadedModulesMethods[module] = api.AutoCompletion[module]
-- 
cgit v1.2.3


From b3c07f167f8b82d1079abe6e15cd1f480712b030 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <basvankervel@gmail.com>
Date: Thu, 11 Jun 2015 15:06:12 +0200
Subject: fixed incomplete merge action

---
 cmd/console/js.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'cmd/console')

diff --git a/cmd/console/js.go b/cmd/console/js.go
index 5aff8acfd..a5fdaacc2 100644
--- a/cmd/console/js.go
+++ b/cmd/console/js.go
@@ -84,7 +84,7 @@ func loadAutoCompletion(js *jsre, ipcpath string) {
 	if err != nil {
 		utils.Fatalf("Unable to determine supported modules - %v", err)
 	}
-	
+
 	loadedModulesMethods = make(map[string][]string)
 	for module, _ := range modules {
 		loadedModulesMethods[module] = api.AutoCompletion[module]
-- 
cgit v1.2.3


From 359e6414e50df415caa1d4411224c6d48b6cb798 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Fri, 12 Jun 2015 09:32:37 +0200
Subject: fixed windows ipc path issue

---
 cmd/console/main.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'cmd/console')

diff --git a/cmd/console/main.go b/cmd/console/main.go
index 9020a12fe..365dbec56 100644
--- a/cmd/console/main.go
+++ b/cmd/console/main.go
@@ -93,7 +93,7 @@ func main() {
 
 func run(ctx *cli.Context) {
 	jspath := ctx.GlobalString(utils.JSpathFlag.Name)
-	ipcpath := ctx.GlobalString(utils.IPCPathFlag.Name)
+	ipcpath := utils.IpcSocketPath(ctx)
 
 	repl := newJSRE(jspath, ipcpath)
 	repl.welcome(ipcpath)
-- 
cgit v1.2.3


From 55a796b7c3a9560f27b0bfc7fe064e84d1b36608 Mon Sep 17 00:00:00 2001
From: Bas van Kervel <bas@ethdev.com>
Date: Fri, 12 Jun 2015 09:42:57 +0200
Subject: removed obsolete console flag

---
 cmd/console/main.go | 1 -
 1 file changed, 1 deletion(-)

(limited to 'cmd/console')

diff --git a/cmd/console/main.go b/cmd/console/main.go
index 365dbec56..e8dd412ba 100644
--- a/cmd/console/main.go
+++ b/cmd/console/main.go
@@ -52,7 +52,6 @@ func init() {
 
 	app.Action = run
 	app.Flags = []cli.Flag{
-		utils.IPCDisabledFlag,
 		utils.IPCPathFlag,
 		utils.VerbosityFlag,
 		utils.JSpathFlag,
-- 
cgit v1.2.3