aboutsummaryrefslogtreecommitdiffstats
path: root/console
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-08-01 23:45:17 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-08-09 16:30:17 +0800
commitdb568a61e2a98880ab308bf2224aa34073dc7f39 (patch)
tree97da46661ad3002b6ff9f6dca07e3105da5a9c5a /console
parent17ce0a37de5a2712a8bf9d58df705e718b3b2cd6 (diff)
downloaddexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.gz
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.zst
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.zip
accounts, console, internal: support trezor hardware wallet
Diffstat (limited to 'console')
-rw-r--r--console/bridge.go49
-rw-r--r--console/console.go12
2 files changed, 58 insertions, 3 deletions
diff --git a/console/bridge.go b/console/bridge.go
index 75be68188..b2d4e0974 100644
--- a/console/bridge.go
+++ b/console/bridge.go
@@ -23,6 +23,7 @@ import (
"strings"
"time"
+ "github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/robertkrimen/otto"
@@ -83,6 +84,54 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
return ret
}
+// OpenWallet is a wrapper around personal.openWallet which can interpret and
+// react to certain error messages, such as the Trezor PIN matrix request.
+func (b *bridge) OpenWallet(call otto.FunctionCall) (response otto.Value) {
+ // Make sure we have an wallet specified to open
+ if !call.Argument(0).IsString() {
+ throwJSException("first argument must be the wallet URL to open")
+ }
+ wallet := call.Argument(0)
+
+ var passwd otto.Value
+ if call.Argument(1).IsUndefined() || call.Argument(1).IsNull() {
+ passwd, _ = otto.ToValue("")
+ } else {
+ passwd = call.Argument(1)
+ }
+ // Open the wallet and return if successful in itself
+ val, err := call.Otto.Call("jeth.openWallet", nil, wallet, passwd)
+ if err == nil {
+ return val
+ }
+ // Wallet open failed, report error unless it's a PIN entry
+ if !strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()) {
+ throwJSException(err.Error())
+ }
+ // Trezor PIN matrix input requested, display the matrix to the user and fetch the data
+ fmt.Fprintf(b.printer, "Look at the device for number positions\n\n")
+ fmt.Fprintf(b.printer, "a | b | c\n")
+ fmt.Fprintf(b.printer, "--+---+--\n")
+ fmt.Fprintf(b.printer, "d | e | f\n")
+ fmt.Fprintf(b.printer, "--+---+--\n")
+ fmt.Fprintf(b.printer, "g | h | i\n\n")
+
+ if input, err := b.prompter.PromptPassword("Please enter current PIN: "); err != nil {
+ throwJSException(err.Error())
+ } else {
+ // Transform the alphabetical input to numbers
+ mapping := map[string]string{"a": "7", "b": "8", "c": "9", "d": "4", "e": "5", "f": "6", "g": "1", "h": "2", "i": "3"}
+ for from, to := range mapping {
+ input = strings.Replace(input, from, to, -1)
+ }
+ passwd, _ = otto.ToValue(input)
+ }
+ if val, err = call.Otto.Call("jeth.openWallet", nil, wallet, passwd); err != nil {
+ throwJSException(err.Error())
+ }
+ return val
+}
+
// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
// uses a non-echoing password prompt to acquire the passphrase and executes the
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
diff --git a/console/console.go b/console/console.go
index 389d52858..3cd2ad34b 100644
--- a/console/console.go
+++ b/console/console.go
@@ -160,10 +160,15 @@ func (c *Console) init(preload []string) error {
if err != nil {
return err
}
- // Override the unlockAccount, newAccount and sign methods since these require user interaction.
- // Assign these method in the Console the original web3 callbacks. These will be called by the jeth.*
- // methods after they got the password from the user and send the original web3 request to the backend.
+ // Override the openWallet, unlockAccount, newAccount and sign methods since
+ // these require user interaction. Assign these method in the Console the
+ // original web3 callbacks. These will be called by the jeth.* methods after
+ // they got the password from the user and send the original web3 request to
+ // the backend.
if obj := personal.Object(); obj != nil { // make sure the personal api is enabled over the interface
+ if _, err = c.jsre.Run(`jeth.openWallet = personal.openWallet;`); err != nil {
+ return fmt.Errorf("personal.openWallet: %v", err)
+ }
if _, err = c.jsre.Run(`jeth.unlockAccount = personal.unlockAccount;`); err != nil {
return fmt.Errorf("personal.unlockAccount: %v", err)
}
@@ -173,6 +178,7 @@ func (c *Console) init(preload []string) error {
if _, err = c.jsre.Run(`jeth.sign = personal.sign;`); err != nil {
return fmt.Errorf("personal.sign: %v", err)
}
+ obj.Set("openWallet", bridge.OpenWallet)
obj.Set("unlockAccount", bridge.UnlockAccount)
obj.Set("newAccount", bridge.NewAccount)
obj.Set("sign", bridge.Sign)