diff --git a/cmd/subcommands/command.go b/cmd/subcommands/command.go index d875c5c..ec12f05 100644 --- a/cmd/subcommands/command.go +++ b/cmd/subcommands/command.go @@ -1,9 +1,10 @@ package cmd import ( - "fmt" - "github.com/ethereum/go-ethereum/rpc" + ethereum_rpc "github.com/ethereum/go-ethereum/rpc" + "github.com/harmony-one/go-sdk/pkg/common" "github.com/harmony-one/go-sdk/pkg/console" + "github.com/harmony-one/go-sdk/pkg/rpc" "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "log" @@ -12,26 +13,24 @@ import ( ) func init() { - shardNum := 0 net := "mainnet" cmdCommand := &cobra.Command{ Use: "command", Short: "Start an interactive JavaScript environment (connect to node)", RunE: func(cmd *cobra.Command, args []string) error { - return openConsole(net, shardNum) + return openConsole(net) }, } - cmdCommand.Flags().IntVar(&shardNum, "shard", 0, "used shard(default: 0)") - cmdCommand.Flags().StringVar(&net, "net", "mainnet", "used net(default: mainnet, choose: mainnet or testnet)") + cmdCommand.Flags().StringVar(&net, "net", "mainnet", "used net(default: mainnet, eg: mainnet, testnet ...)") RootCmd.AddCommand(cmdCommand) } func checkAndMakeDirIfNeeded() string { userDir, _ := homedir.Dir() - hmyCLIDir := path.Join(userDir, ".hmy_cli", "command") + hmyCLIDir := path.Join(userDir, common.DefaultConfigDirName, common.DefaultCommandAliasesDirName) if _, err := os.Stat(hmyCLIDir); os.IsNotExist(err) { // Double check with Leo what is right file persmission os.Mkdir(hmyCLIDir, 0700) @@ -40,37 +39,34 @@ func checkAndMakeDirIfNeeded() string { return hmyCLIDir } -// remoteConsole will connect to a remote geth instance, attaching a JavaScript +// remoteConsole will connect to a remote node instance, attaching a JavaScript // console to it. -func openConsole(net string, shard int) error { - var netMap = map[string]string{ - "mainnet-0": "https://api.harmony.one", - "mainnet-1": "https://s1.api.harmony.one", - "mainnet-2": "https://s2.api.harmony.one", - "mainnet-3": "https://s3.api.harmony.one", - "testnet-0": "https://api.s0.b.hmny.io", - "testnet-1": "https://api.s1.b.hmny.io", - "testnet-2": "https://api.s2.b.hmny.io", - "testnet-3": "https://api.s3.b.hmny.io", +func openConsole(net string) error { + client, err := ethereum_rpc.Dial(node) + if err != nil { + log.Fatalf("Unable to attach to remote node: %v", err) } - endpoint := "" - if findedEndpoint, ok := netMap[fmt.Sprintf("%s-%d", net, shard)]; ok { - endpoint = findedEndpoint - } else { - log.Fatalf("Unknown network `%s` or shardId `%d`", net, shard) + // check net type + _, err = common.StringToChainID(net) + if err != nil { + return err } - client, err := rpc.Dial(endpoint) + // get shard id + nodeRPCReply, err := rpc.Request(rpc.Method.GetShardID, node, []interface{}{}) if err != nil { - log.Fatalf("Unable to attach to remote geth: %v", err) + return err } + + shard := int(nodeRPCReply["result"].(float64)) + config := console.Config{ DataDir: checkAndMakeDirIfNeeded(), DocRoot: ".", Client: client, Preload: nil, - NodeUrl: endpoint, + NodeUrl: node, ShardId: shard, Net: net, } diff --git a/pkg/common/values.go b/pkg/common/values.go index 52959b9..2dd86e1 100644 --- a/pkg/common/values.go +++ b/pkg/common/values.go @@ -10,6 +10,7 @@ import ( const ( DefaultConfigDirName = ".hmy_cli" DefaultConfigAccountAliasesDirName = "account-keys" + DefaultCommandAliasesDirName = "command" DefaultPassphrase = "" JSONRPCVersion = "2.0" Secp256k1PrivateKeyBytesLength = 32 diff --git a/pkg/console/bridge.go b/pkg/console/bridge.go index 6b47f8c..4256273 100644 --- a/pkg/console/bridge.go +++ b/pkg/console/bridge.go @@ -15,7 +15,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -// bridge is a collection of JavaScript utility methods to bride the .js runtime +// bridge is a collection of JavaScript utility methods to bridge the .js runtime // environment and the Go RPC connection backing the remote method calls. type bridge struct { client *rpc.Client // RPC client to execute Ethereum requests through diff --git a/pkg/console/console.go b/pkg/console/console.go index ecd1ce7..a9acb5a 100644 --- a/pkg/console/console.go +++ b/pkg/console/console.go @@ -1,21 +1,33 @@ package console import ( + "encoding/hex" + "errors" "fmt" - "github.com/ethereum/go-ethereum/rpc" + ethereum_rpc "github.com/ethereum/go-ethereum/rpc" + "github.com/harmony-one/go-sdk/pkg/account" + "github.com/harmony-one/go-sdk/pkg/address" + "github.com/harmony-one/go-sdk/pkg/common" "github.com/harmony-one/go-sdk/pkg/console/jsre" "github.com/harmony-one/go-sdk/pkg/console/jsre/deps" "github.com/harmony-one/go-sdk/pkg/console/prompt" "github.com/harmony-one/go-sdk/pkg/console/web3ext" + "github.com/harmony-one/go-sdk/pkg/rpc" + "github.com/harmony-one/go-sdk/pkg/store" + "github.com/harmony-one/go-sdk/pkg/transaction" + "github.com/harmony-one/harmony/accounts" "io" "io/ioutil" + "math/big" "os" "os/signal" "path/filepath" "regexp" "sort" + "strconv" "strings" "syscall" + "time" "github.com/dop251/goja" "github.com/mattn/go-colorable" @@ -38,32 +50,32 @@ const DefaultPrompt = "> " // Config is the collection of configurations to fine tune the behavior of the // JavaScript console. type Config struct { - DataDir string // Data directory to store the console history at - DocRoot string // Filesystem path from where to load JavaScript files from - Client *rpc.Client // RPC client to execute Ethereum requests through - Prompt string // Input prompt prefix string (defaults to DefaultPrompt) - Prompter prompt.UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter) - Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout) - Preload []string // Absolute paths to JavaScript files to preload - NodeUrl string // Hmy Node url - ShardId int // Hmy Shard ID - Net string // Hmy Network + DataDir string // Data directory to store the console history at + DocRoot string // Filesystem path from where to load JavaScript files from + Client *ethereum_rpc.Client // RPC client to execute Ethereum requests through + Prompt string // Input prompt prefix string (defaults to DefaultPrompt) + Prompter prompt.UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter) + Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout) + Preload []string // Absolute paths to JavaScript files to preload + NodeUrl string // Hmy Node url + ShardId int // Hmy Shard ID + Net string // Hmy Network } // Console is a JavaScript interpreted runtime environment. It is a fully fledged // JavaScript console attached to a running node via an external or in-process RPC // client. type Console struct { - client *rpc.Client // RPC client to execute Ethereum requests through - jsre *jsre.JSRE // JavaScript runtime environment running the interpreter - prompt string // Input prompt prefix string - prompter prompt.UserPrompter // Input prompter to allow interactive user feedback - histPath string // Absolute path to the console scrollback history - history []string // Scroll history maintained by the console - printer io.Writer // Output writer to serialize any display strings to - nodeUrl string // Hmy Node url - shardId int // Hmy Shard ID - net string // Hmy Network + client *ethereum_rpc.Client // RPC client to execute Ethereum requests through + jsre *jsre.JSRE // JavaScript runtime environment running the interpreter + prompt string // Input prompt prefix string + prompter prompt.UserPrompter // Input prompter to allow interactive user feedback + histPath string // Absolute path to the console scrollback history + history []string // Scroll history maintained by the console + printer io.Writer // Output writer to serialize any display strings to + nodeUrl string // Hmy Node url + shardId int // Hmy Shard ID + net string // Hmy Network } // New initializes a JavaScript interpreted runtime environment and sets defaults @@ -493,3 +505,252 @@ func (c *Console) Stop(graceful bool) error { c.jsre.Stop(graceful) return nil } + +func (b *bridge) callbackProtected(protectedFunc func(call jsre.Call) (goja.Value, error)) func(call jsre.Call) (goja.Value, error) { + return func(call jsre.Call) (goja.Value, error) { + var availableCB goja.Callable = nil + for i, args := range call.Arguments { + if cb, ok := goja.AssertFunction(args); ok { + availableCB = cb + call.Arguments = call.Arguments[:i] // callback must be last + break + } + } + + value, err := protectedFunc(call) + jsErr := goja.Undefined() + if err != nil { + jsErr = call.VM.NewGoError(err) + } + if availableCB != nil { + _, _ = availableCB(nil, jsErr, value) + } + + return value, err + } +} + +func (b *bridge) HmyGetListAccounts(call jsre.Call) (goja.Value, error) { + var accounts = []string{} + + for _, name := range store.LocalAccounts() { + ks := store.FromAccountName(name) + allAccounts := ks.Accounts() + for _, account := range allAccounts { + accounts = append(accounts, account.Address.String()) + } + } + + return call.VM.ToValue(accounts), nil +} + +func (b *bridge) HmySignTransaction(call jsre.Call) (goja.Value, error) { + txObj := call.Arguments[0].ToObject(call.VM) + password := call.Arguments[1].String() + + from := getStringFromJsObjWithDefault(txObj, "from", "") + to := getStringFromJsObjWithDefault(txObj, "to", "") + gasLimit := getStringFromJsObjWithDefault(txObj, "gas", "1000000") + amount := getStringFromJsObjWithDefault(txObj, "value", "0") + gasPrice := getStringFromJsObjWithDefault(txObj, "gasPrice", "1") + + networkHandler := rpc.NewHTTPHandler(b.console.nodeUrl) + chanId, err := common.StringToChainID(b.console.net) + if err != nil { + return nil, err + } + + ks, acct, err := store.UnlockedKeystore(from, password) + if err != nil { + return nil, err + } + ctrlr := transaction.NewController(networkHandler, ks, acct, *chanId, func(controller *transaction.Controller) { + // nop + }) + + tempLimit, err := strconv.ParseInt(gasLimit, 10, 64) + if err != nil { + return nil, err + } + if tempLimit < 0 { + return nil, errors.New(fmt.Sprintf("gas-limit can not be negative: %s", gasLimit)) + } + gLimit := uint64(tempLimit) + + amt, err := common.NewDecFromString(amount) + if err != nil { + return nil, fmt.Errorf("amount %w", err) + } + + gPrice, err := common.NewDecFromString(gasPrice) + if err != nil { + return nil, fmt.Errorf("gas-price %w", err) + } + + toP := &to + if to == "" { + toP = nil + } + + nonce := transaction.GetNextPendingNonce(from, networkHandler) + err = ctrlr.SignTransaction( + nonce, gLimit, + toP, + uint32(b.console.shardId), uint32(b.console.shardId), + amt, gPrice, + []byte{}, + ) + if err != nil { + return nil, err + } + + info := ctrlr.TransactionInfo() + + return call.VM.ToValue(map[string]interface{}{ + "raw": ctrlr.RawTransaction(), + "tx": map[string]string{ + "nonce": "0x" + big.NewInt(int64(info.Nonce())).Text(16), + "gasPrice": "0x" + info.GasPrice().Text(16), + "gas": "0x" + big.NewInt(int64(info.GasLimit())).Text(16), + "to": info.To().Hex(), + "value": "0x" + info.Value().Text(16), + "input": "0x" + hex.EncodeToString(info.Data()), + "v": "0x" + info.V().Text(16), + "r": "0x" + info.R().Text(16), + "s": "0x" + info.S().Text(16), + "hash": info.Hash().Hex(), + }, + }), nil +} + +func (b *bridge) HmySendTransaction(call jsre.Call) (goja.Value, error) { + txObj := call.Arguments[0].ToObject(call.VM) + password := "" + if len(call.Arguments) > 1 { + password = call.Arguments[1].String() + } + + from := getStringFromJsObjWithDefault(txObj, "from", "") + to := getStringFromJsObjWithDefault(txObj, "to", "") + gasLimit := getStringFromJsObjWithDefault(txObj, "gas", "1000000") + amount := getStringFromJsObjWithDefault(txObj, "value", "0") + gasPrice := getStringFromJsObjWithDefault(txObj, "gasPrice", "1") + + networkHandler := rpc.NewHTTPHandler(b.console.nodeUrl) + chanId, err := common.StringToChainID(b.console.net) + if err != nil { + return nil, err + } + + ks, acct, err := store.UnlockedKeystore(from, password) + if err != nil { + return nil, err + } + ctrlr := transaction.NewController(networkHandler, ks, acct, *chanId, func(controller *transaction.Controller) { + // nop + }) + + tempLimit, err := strconv.ParseInt(gasLimit, 10, 64) + if err != nil { + return nil, err + } + if tempLimit < 0 { + return nil, errors.New(fmt.Sprintf("gas-limit can not be negative: %s", gasLimit)) + } + gLimit := uint64(tempLimit) + + amt, err := common.NewDecFromString(amount) + if err != nil { + return nil, fmt.Errorf("amount %w", err) + } + + gPrice, err := common.NewDecFromString(gasPrice) + if err != nil { + return nil, fmt.Errorf("gas-price %w", err) + } + + toP := &to + if to == "" { + toP = nil + } + + nonce := transaction.GetNextPendingNonce(from, networkHandler) + err = ctrlr.ExecuteTransaction( + nonce, gLimit, + toP, + uint32(b.console.shardId), uint32(b.console.shardId), + amt, gPrice, + []byte{}, + ) + if err != nil { + return nil, err + } + + return call.VM.ToValue(*ctrlr.TransactionHash()), nil +} + +func (b *bridge) HmyLockAccount(call jsre.Call) (goja.Value, error) { + address := call.Arguments[0].String() + + _, _, err := store.LockKeystore(address) + if err != nil { + return nil, err + } + + return goja.Null(), nil +} + +func (b *bridge) HmyImportRawKey(call jsre.Call) (goja.Value, error) { + privateKey := call.Arguments[0].String() + password := call.Arguments[1].String() + + name, err := account.ImportFromPrivateKey(privateKey, "", password) + if err != nil { + return nil, err + } + + return call.VM.ToValue(name), nil +} + +func (b *bridge) HmyUnlockAccount(call jsre.Call) (goja.Value, error) { + if len(call.Arguments) < 3 { + return nil, errors.New("arguments < 3") + } + address := call.Arguments[0].String() + password := call.Arguments[1].String() + unlockDuration := call.Arguments[2].ToInteger() + + _, _, err := store.UnlockedKeystoreTimeLimit(address, password, time.Duration(unlockDuration)*time.Second) + if err != nil { + return nil, err + } + + return goja.Null(), nil +} + +func (b *bridge) HmyNewAccount(call jsre.Call) (goja.Value, error) { + return goja.Null(), nil +} + +func (b *bridge) HmySign(call jsre.Call) (goja.Value, error) { + dataToSign := call.Arguments[0].String() + addressStr := call.Arguments[1].String() + password := call.Arguments[2].String() + + ks := store.FromAddress(addressStr) + if ks == nil { + return nil, fmt.Errorf("could not open local keystore for %s", addressStr) + } + + acc, err := ks.Find(accounts.Account{Address: address.Parse(addressStr)}) + if err != nil { + return nil, err + } + + message, err := signMessageWithPassword(ks, acc, password, []byte(dataToSign)) + if err != nil { + return nil, err + } + + return call.VM.ToValue(hex.EncodeToString(message)), nil +} diff --git a/pkg/console/hmy.go b/pkg/console/hmy.go index a8b5e11..f129a7a 100644 --- a/pkg/console/hmy.go +++ b/pkg/console/hmy.go @@ -1,283 +1,14 @@ package console import ( - "encoding/hex" - "errors" "fmt" "github.com/dop251/goja" - "github.com/harmony-one/go-sdk/pkg/account" - "github.com/harmony-one/go-sdk/pkg/address" - "github.com/harmony-one/go-sdk/pkg/common" - "github.com/harmony-one/go-sdk/pkg/console/jsre" - "github.com/harmony-one/go-sdk/pkg/rpc" - "github.com/harmony-one/go-sdk/pkg/store" - "github.com/harmony-one/go-sdk/pkg/transaction" "github.com/harmony-one/harmony/accounts" "github.com/harmony-one/harmony/accounts/keystore" "github.com/harmony-one/harmony/crypto/hash" - "math/big" "strconv" - "time" ) -func getStringFromJsObjWithDefault(o *goja.Object, key string, def string) string { - get := o.Get(key) - if get == nil { - return def - } else { - return get.String() - } -} - -func (b *bridge) callbackProtected(protectedFunc func(call jsre.Call) (goja.Value, error)) func(call jsre.Call) (goja.Value, error) { - return func(call jsre.Call) (goja.Value, error) { - var availableCB goja.Callable = nil - for i, args := range call.Arguments { - if cb, ok := goja.AssertFunction(args); ok { - availableCB = cb - call.Arguments = call.Arguments[:i] // callback must be last - break - } - } - - value, err := protectedFunc(call) - jsErr := goja.Undefined() - if err != nil { - jsErr = call.VM.NewGoError(err) - } - if availableCB != nil { - _, _ = availableCB(nil, jsErr, value) - } - - return value, err - } -} - -func (b *bridge) HmyGetListAccounts(call jsre.Call) (goja.Value, error) { - var accounts = []string{} - - for _, name := range store.LocalAccounts() { - ks := store.FromAccountName(name) - allAccounts := ks.Accounts() - for _, account := range allAccounts { - accounts = append(accounts, account.Address.String()) - } - } - - return call.VM.ToValue(accounts), nil -} - -func (b *bridge) HmySignTransaction(call jsre.Call) (goja.Value, error) { - txObj := call.Arguments[0].ToObject(call.VM) - password := call.Arguments[1].String() - - from := getStringFromJsObjWithDefault(txObj, "from", "") - to := getStringFromJsObjWithDefault(txObj, "to", "") - gasLimit := getStringFromJsObjWithDefault(txObj, "gas", "1000000") - amount := getStringFromJsObjWithDefault(txObj, "value", "0") - gasPrice := getStringFromJsObjWithDefault(txObj, "gasPrice", "1") - - networkHandler := rpc.NewHTTPHandler(b.console.nodeUrl) - chanId, err := common.StringToChainID(b.console.net) - if err != nil { - return nil, err - } - - ks, acct, err := store.UnlockedKeystore(from, password) - if err != nil { - return nil, err - } - ctrlr := transaction.NewController(networkHandler, ks, acct, *chanId, func(controller *transaction.Controller) { - // nop - }) - - tempLimit, err := strconv.ParseInt(gasLimit, 10, 64) - if err != nil { - return nil, err - } - if tempLimit < 0 { - return nil, errors.New(fmt.Sprintf("gas-limit can not be negative: %s", gasLimit)) - } - gLimit := uint64(tempLimit) - - amt, err := common.NewDecFromString(amount) - if err != nil { - return nil, fmt.Errorf("amount %w", err) - } - - gPrice, err := common.NewDecFromString(gasPrice) - if err != nil { - return nil, fmt.Errorf("gas-price %w", err) - } - - toP := &to - if to == "" { - toP = nil - } - - nonce := transaction.GetNextPendingNonce(from, networkHandler) - err = ctrlr.SignTransaction( - nonce, gLimit, - toP, - uint32(b.console.shardId), uint32(b.console.shardId), - amt, gPrice, - []byte{}, - ) - if err != nil { - return nil, err - } - - info := ctrlr.TransactionInfo() - - return call.VM.ToValue(map[string]interface{}{ - "raw": ctrlr.RawTransaction(), - "tx": map[string]string{ - "nonce": "0x" + big.NewInt(int64(info.Nonce())).Text(16), - "gasPrice": "0x" + info.GasPrice().Text(16), - "gas": "0x" + big.NewInt(int64(info.GasLimit())).Text(16), - "to": info.To().Hex(), - "value": "0x" + info.Value().Text(16), - "input": "0x" + hex.EncodeToString(info.Data()), - "v": "0x" + info.V().Text(16), - "r": "0x" + info.R().Text(16), - "s": "0x" + info.S().Text(16), - "hash": info.Hash().Hex(), - }, - }), nil -} - -func (b *bridge) HmySendTransaction(call jsre.Call) (goja.Value, error) { - txObj := call.Arguments[0].ToObject(call.VM) - password := "" - if len(call.Arguments) > 1 { - password = call.Arguments[1].String() - } - - from := getStringFromJsObjWithDefault(txObj, "from", "") - to := getStringFromJsObjWithDefault(txObj, "to", "") - gasLimit := getStringFromJsObjWithDefault(txObj, "gas", "1000000") - amount := getStringFromJsObjWithDefault(txObj, "value", "0") - gasPrice := getStringFromJsObjWithDefault(txObj, "gasPrice", "1") - - networkHandler := rpc.NewHTTPHandler(b.console.nodeUrl) - chanId, err := common.StringToChainID(b.console.net) - if err != nil { - return nil, err - } - - ks, acct, err := store.UnlockedKeystore(from, password) - if err != nil { - return nil, err - } - ctrlr := transaction.NewController(networkHandler, ks, acct, *chanId, func(controller *transaction.Controller) { - // nop - }) - - tempLimit, err := strconv.ParseInt(gasLimit, 10, 64) - if err != nil { - return nil, err - } - if tempLimit < 0 { - return nil, errors.New(fmt.Sprintf("gas-limit can not be negative: %s", gasLimit)) - } - gLimit := uint64(tempLimit) - - amt, err := common.NewDecFromString(amount) - if err != nil { - return nil, fmt.Errorf("amount %w", err) - } - - gPrice, err := common.NewDecFromString(gasPrice) - if err != nil { - return nil, fmt.Errorf("gas-price %w", err) - } - - toP := &to - if to == "" { - toP = nil - } - - nonce := transaction.GetNextPendingNonce(from, networkHandler) - err = ctrlr.ExecuteTransaction( - nonce, gLimit, - toP, - uint32(b.console.shardId), uint32(b.console.shardId), - amt, gPrice, - []byte{}, - ) - if err != nil { - return nil, err - } - - return call.VM.ToValue(*ctrlr.TransactionHash()), nil -} - -func (b *bridge) HmyLockAccount(call jsre.Call) (goja.Value, error) { - address := call.Arguments[0].String() - - _, _, err := store.LockKeystore(address) - if err != nil { - return nil, err - } - - return goja.Null(), nil -} - -func (b *bridge) HmyImportRawKey(call jsre.Call) (goja.Value, error) { - privateKey := call.Arguments[0].String() - password := call.Arguments[1].String() - - name, err := account.ImportFromPrivateKey(privateKey, "", password) - if err != nil { - return nil, err - } - - return call.VM.ToValue(name), nil -} - -func (b *bridge) HmyUnlockAccount(call jsre.Call) (goja.Value, error) { - if len(call.Arguments) < 3 { - return nil, errors.New("arguments < 3") - } - address := call.Arguments[0].String() - password := call.Arguments[1].String() - unlockDuration := call.Arguments[2].ToInteger() - - _, _, err := store.UnlockedKeystoreTimeLimit(address, password, time.Duration(unlockDuration)*time.Second) - if err != nil { - return nil, err - } - - return goja.Null(), nil -} - -func (b *bridge) HmyNewAccount(call jsre.Call) (goja.Value, error) { - return goja.Null(), nil -} - -func (b *bridge) HmySign(call jsre.Call) (goja.Value, error) { - dataToSign := call.Arguments[0].String() - addressStr := call.Arguments[1].String() - password := call.Arguments[2].String() - - ks := store.FromAddress(addressStr) - if ks == nil { - return nil, fmt.Errorf("could not open local keystore for %s", addressStr) - } - - acc, err := ks.Find(accounts.Account{Address: address.Parse(addressStr)}) - if err != nil { - return nil, err - } - - message, err := signMessageWithPassword(ks, acc, password, []byte(dataToSign)) - if err != nil { - return nil, err - } - - return call.VM.ToValue(hex.EncodeToString(message)), nil -} - func signMessageWithPassword(keyStore *keystore.KeyStore, account accounts.Account, password string, data []byte) (sign []byte, err error) { signData := append([]byte("\x19Ethereum Signed Message:\n" + strconv.Itoa(len(data)))) msgHash := hash.Keccak256(append(signData, data...)) @@ -294,3 +25,12 @@ func signMessageWithPassword(keyStore *keystore.KeyStore, account accounts.Accou sign[64] += 0x1b return sign, nil } + +func getStringFromJsObjWithDefault(o *goja.Object, key string, def string) string { + get := o.Get(key) + if get == nil { + return def + } else { + return get.String() + } +} diff --git a/pkg/console/jsre/completion.go b/pkg/console/jsre/completion.go index abbef9a..2c10518 100644 --- a/pkg/console/jsre/completion.go +++ b/pkg/console/jsre/completion.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package jsre import ( diff --git a/pkg/console/jsre/completion_test.go b/pkg/console/jsre/completion_test.go index 42c92ad..2d05547 100644 --- a/pkg/console/jsre/completion_test.go +++ b/pkg/console/jsre/completion_test.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package jsre import ( diff --git a/pkg/console/jsre/jsre.go b/pkg/console/jsre/jsre.go index 7980f16..9a79367 100644 --- a/pkg/console/jsre/jsre.go +++ b/pkg/console/jsre/jsre.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package jsre import ( diff --git a/pkg/console/jsre/jsre_test.go b/pkg/console/jsre/jsre_test.go index 930cfa5..4a272f3 100644 --- a/pkg/console/jsre/jsre_test.go +++ b/pkg/console/jsre/jsre_test.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package jsre import ( diff --git a/pkg/console/jsre/pretty.go b/pkg/console/jsre/pretty.go index 4f9c4e8..4171e00 100644 --- a/pkg/console/jsre/pretty.go +++ b/pkg/console/jsre/pretty.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package jsre import ( diff --git a/pkg/console/prompt/prompter.go b/pkg/console/prompt/prompter.go index 45ffa0d..810b6c3 100644 --- a/pkg/console/prompt/prompter.go +++ b/pkg/console/prompt/prompter.go @@ -1,3 +1,19 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package prompt import (