diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 9d27248d7..55ddcfe09 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "net/http" "os" "path/filepath" @@ -12,18 +13,18 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - cryptoKeys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/tendermint/p2p" - ctypes "github.com/tendermint/tendermint/rpc/core/types" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" + "github.com/chain/core/config" + client "github.com/cosmos/cosmos-sdk/client" keys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/tests" - "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/wire" + auth "github.com/cosmos/cosmos-sdk/x/auth/rest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + p2p "github.com/tendermint/go-p2p" + "github.com/tendermint/mintdb/types" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tmlibs/log" ) func TestKeys(t *testing.T) { @@ -299,9 +300,53 @@ func setupEnvironment(t *testing.T) (kill func(), port string, seed string) { cmdNode.Process.Wait() os.Remove(dir) } +} + +// strt TM and the LCD in process, listening on their respective sockets +func startTMAndLCD(t *testing.T) (kill func(), port string, seed string) { + + // make the keybase and its key ... + + startTM(cfg, genDoc, app) + startLCD(cdc, listenAddr, logger) + + kill = func() { + // TODO: cleanup + // TODO: it would be great if TM could run without + // persiting anything in the first place + } return kill, port, seed } +// Create & start in-process tendermint node with memdb +// and in-process abci application. +// TODO: need to clean up the WAL dir or enable it to be not persistent +func startTM(cfg *config.Config, genDoc types.GenesisDoc, app abci.Application) (*Node, error) { + genDocProvider := func() (*types.GenesisDoc, error) { return genDoc, nil } + dbProvider := func() (*dbm.DB, error) { return dbm.NewMemDB(), nil } + n, err := node.NewNode(cfg, + privVal, + proxy.NewLocalClientCreator(app), + genDocProvider, + dbProvider, + logger.With("module", "node")) + if err != nil { + return nil, err + } + + err = n.Start() + if err != nil { + return nil, err + } + return n, err +} + +// start the LCD. note this blocks! +func startLCD(cdc *wire.Codec, listenAddr string, logger log.Logger) (net.Listener, error) { + handler := createHandler(cdc) + return StartHTTPServer(listenAddr, handler, logger) +} + func request(t *testing.T, port, method, path string, payload []byte) (*http.Response, string) { var res *http.Response var err error diff --git a/client/lcd/main_test.go b/client/lcd/main_test.go new file mode 100644 index 000000000..404309821 --- /dev/null +++ b/client/lcd/main_test.go @@ -0,0 +1,24 @@ +package client_test + +import ( + "os" + "testing" + + nm "github.com/tendermint/tendermint/node" +) + +var node *nm.Node + +// See https://golang.org/pkg/testing/#hdr-Main +// for more details +func TestMain(m *testing.M) { + // start a basecoind node and LCD server in the background to test against + + // run all the tests against a single server instance + code := m.Run() + + // tear down + + // + os.Exit(code) +} diff --git a/client/lcd/root.go b/client/lcd/root.go index 8476d16d5..b0ffa2f6d 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -2,10 +2,12 @@ package lcd import ( "net/http" + "os" "github.com/gorilla/mux" "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/tendermint/tmlibs/log" client "github.com/cosmos/cosmos-sdk/client" keys "github.com/cosmos/cosmos-sdk/client/keys" @@ -18,8 +20,8 @@ import ( ) const ( - flagBind = "bind" - flagCORS = "cors" + flagListenAddr = "laddr" + flagCORS = "cors" ) // ServeCommand will generate a long-running rest server @@ -29,25 +31,35 @@ func ServeCommand(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "rest-server", Short: "Start LCD (light-client daemon), a local REST server", - RunE: startRESTServer(cdc), + RunE: startRESTServerFn(cdc), } - // TODO: handle unix sockets also? - cmd.Flags().StringP(flagBind, "b", "localhost:1317", "Interface and port that server binds to") + cmd.Flags().StringP(flagListenAddr, "a", "tcp://localhost:1317", "Address for server to listen on") cmd.Flags().String(flagCORS, "", "Set to domains that can make CORS requests (* for all)") cmd.Flags().StringP(client.FlagChainID, "c", "", "ID of chain we connect to") cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to") return cmd } -func startRESTServer(cdc *wire.Codec) func(cmd *cobra.Command, args []string) error { +func startRESTServerFn(cdc *wire.Codec) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { - bind := viper.GetString(flagBind) - r := initRouter(cdc) - return http.ListenAndServe(bind, r) + listenAddr := viper.GetString(flagListenAddr) + handler := createHandler(cdc) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)). + With("module", "rest-server") + listener, err := StartHTTPServer(listenAddr, handler, logger) + if err != nil { + return err + } + + // Wait forever and cleanup + cmn.TrapSignal(func() { + err := listener.Close() + logger.Error("Error closing listener", "err", err) + }) } } -func initRouter(cdc *wire.Codec) http.Handler { +func createHandler(cdc *wire.Codec) http.Handler { r := mux.NewRouter() r.HandleFunc("/version", version.VersionRequestHandler).Methods("GET") diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 5260a90f7..5f7b33790 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -42,6 +42,10 @@ func main() { // get the codec cdc := app.MakeCodec() + // TODO: setup keybase, viper object, etc. to be passed into + // the below functions and eliminate global vars, like we do + // with the cdc + // add standard rpc, and tx commands rpc.AddCommands(basecliCmd) basecliCmd.AddCommand(client.LineBreak) diff --git a/x/bank/rest/root.go b/x/bank/rest/root.go index 77bb991cb..4534482a9 100644 --- a/x/bank/rest/root.go +++ b/x/bank/rest/root.go @@ -1,11 +1,14 @@ package rest import ( - "github.com/cosmos/cosmos-sdk/wire" "github.com/gorilla/mux" + + keys "github.com/tendermint/go-crypto/keys" + + "github.com/cosmos/cosmos-sdk/wire" ) // RegisterRoutes - Central function to define routes that get registered by the main application -func RegisterRoutes(r *mux.Router, cdc *wire.Codec) { - r.HandleFunc("/accounts/{address}/send", SendRequestHandler(cdc)).Methods("POST") +func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { + r.HandleFunc("/accounts/{address}/send", SendRequestHandler(cdc, kb)).Methods("POST") } diff --git a/x/bank/rest/sendtx.go b/x/bank/rest/sendtx.go index 407a53420..4b1c8f12a 100644 --- a/x/bank/rest/sendtx.go +++ b/x/bank/rest/sendtx.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/tendermint/go-crypto/keys" "github.com/cosmos/cosmos-sdk/client/builder" "github.com/cosmos/cosmos-sdk/client/keys" @@ -26,7 +27,7 @@ type sendBody struct { } // SendRequestHandler - http request handler to send coins to a address -func SendRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Request) { +func SendRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.ResponseWriter, *http.Request) { c := commands.Commander{cdc} return func(w http.ResponseWriter, r *http.Request) { // collect data @@ -47,13 +48,6 @@ func SendRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Request return } - kb, err := keys.GetKeyBase() - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return - } - info, err := kb.Get(m.LocalAccountName) if err != nil { w.WriteHeader(http.StatusUnauthorized)