diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-08-01 23:45:17 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2017-08-09 16:30:17 +0800 |
commit | db568a61e2a98880ab308bf2224aa34073dc7f39 (patch) | |
tree | 97da46661ad3002b6ff9f6dca07e3105da5a9c5a /console | |
parent | 17ce0a37de5a2712a8bf9d58df705e718b3b2cd6 (diff) | |
download | dexon-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.go | 49 | ||||
-rw-r--r-- | console/console.go | 12 |
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) |