Expose LCD router, allowing devs to register custom routes from their modules (#2836)

* Fixes #1081
This commit is contained in:
Jack Zampolin 2018-11-16 14:21:36 -08:00 committed by GitHub
parent 15b6fa0959
commit 9676ce7d48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 300 additions and 179 deletions

View File

@ -48,6 +48,7 @@ FEATURES
IMPROVEMENTS IMPROVEMENTS
* Gaia REST API (`gaiacli advanced rest-server`) * Gaia REST API (`gaiacli advanced rest-server`)
* [\#2836](https://github.com/cosmos/cosmos-sdk/pull/2836) Expose LCD router to allow users to register routes there.
* Gaia CLI (`gaiacli`) * Gaia CLI (`gaiacli`)
* [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet * [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet

View File

@ -17,25 +17,32 @@ const (
DefaultGasLimit = 200000 DefaultGasLimit = 200000
GasFlagSimulate = "simulate" GasFlagSimulate = "simulate"
FlagUseLedger = "ledger" FlagUseLedger = "ledger"
FlagChainID = "chain-id" FlagChainID = "chain-id"
FlagNode = "node" FlagNode = "node"
FlagHeight = "height" FlagHeight = "height"
FlagGas = "gas" FlagGas = "gas"
FlagGasAdjustment = "gas-adjustment" FlagGasAdjustment = "gas-adjustment"
FlagTrustNode = "trust-node" FlagTrustNode = "trust-node"
FlagFrom = "from" FlagFrom = "from"
FlagName = "name" FlagName = "name"
FlagAccountNumber = "account-number" FlagAccountNumber = "account-number"
FlagSequence = "sequence" FlagSequence = "sequence"
FlagMemo = "memo" FlagMemo = "memo"
FlagFee = "fee" FlagFee = "fee"
FlagAsync = "async" FlagAsync = "async"
FlagJson = "json" FlagJson = "json"
FlagPrintResponse = "print-response" FlagPrintResponse = "print-response"
FlagDryRun = "dry-run" FlagDryRun = "dry-run"
FlagGenerateOnly = "generate-only" FlagGenerateOnly = "generate-only"
FlagIndentResponse = "indent" FlagIndentResponse = "indent"
FlagListenAddr = "laddr"
FlagCORS = "cors"
FlagMaxOpenConnections = "max-open"
FlagInsecure = "insecure"
FlagSSLHosts = "ssl-hosts"
FlagSSLCertFile = "ssl-certfile"
FlagSSLKeyFile = "ssl-keyfile"
) )
// LineBreak can be included in a command list to provide a blank line // LineBreak can be included in a command list to provide a blank line
@ -92,6 +99,26 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
return cmds return cmds
} }
// RegisterRestServerFlags registers the flags required for rest server
func RegisterRestServerFlags(cmd *cobra.Command) *cobra.Command {
cmd.Flags().String(FlagListenAddr, "tcp://localhost:1317", "The address for the server to listen on")
cmd.Flags().Bool(FlagInsecure, false, "Do not set up SSL/TLS layer")
cmd.Flags().String(FlagSSLHosts, "", "Comma-separated hostnames and IPs to generate a certificate for")
cmd.Flags().String(FlagSSLCertFile, "", "Path to a SSL certificate file. If not supplied, a self-signed certificate will be generated.")
cmd.Flags().String(FlagSSLKeyFile, "", "Path to a key file; ignored if a certificate file is not supplied.")
cmd.Flags().String(FlagCORS, "", "Set the domains that can make CORS requests (* for all)")
cmd.Flags().String(FlagChainID, "", "Chain ID of Tendermint node")
cmd.Flags().String(FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
cmd.Flags().Int(FlagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response")
viper.BindPFlag(FlagTrustNode, cmd.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagChainID, cmd.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, cmd.Flags().Lookup(FlagNode))
return cmd
}
// Gas flag parsing functions // Gas flag parsing functions
// GasSetting encapsulates the possible values passed through the --gas flag. // GasSetting encapsulates the possible values passed through the --gas flag.

View File

@ -2,20 +2,17 @@ package keys
import ( import (
"fmt" "fmt"
"github.com/syndtr/goleveldb/leveldb/opt" "net/http"
"path/filepath" "path/filepath"
"github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/viper"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"net/http"
) )
// KeyDBName is the directory under root where we store the keys // KeyDBName is the directory under root where we store the keys

View File

@ -10,15 +10,9 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
keybase "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/rakyll/statik/fs" "github.com/rakyll/statik/fs"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -27,159 +21,155 @@ import (
tmserver "github.com/tendermint/tendermint/rpc/lib/server" tmserver "github.com/tendermint/tendermint/rpc/lib/server"
) )
const ( // RestServer represents the Light Client Rest server
flagListenAddr = "laddr" type RestServer struct {
flagCORS = "cors" Mux *mux.Router
flagMaxOpenConnections = "max-open" CliCtx context.CLIContext
flagInsecure = "insecure" KeyBase keybase.Keybase
flagSSLHosts = "ssl-hosts" Cdc *codec.Codec
flagSSLCertFile = "ssl-certfile"
flagSSLKeyFile = "ssl-keyfile" log log.Logger
) listener net.Listener
fingerprint string
}
// NewRestServer creates a new rest server instance
func NewRestServer(cdc *codec.Codec) *RestServer {
r := mux.NewRouter()
cliCtx := context.NewCLIContext().WithCodec(cdc)
// Register version methods on the router
r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET")
r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET")
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
return &RestServer{
Mux: r,
CliCtx: cliCtx,
Cdc: cdc,
log: logger,
}
}
func (rs *RestServer) setKeybase(kb keybase.Keybase) {
// If a keybase is passed in, set it and return
if kb != nil {
rs.KeyBase = kb
return
}
// Otherwise get the keybase and set it
kb, err := keys.GetKeyBase() //XXX
if err != nil {
fmt.Printf("Failed to open Keybase: %s, exiting...", err)
os.Exit(1)
}
rs.KeyBase = kb
}
// Start starts the rest server
func (rs *RestServer) Start(listenAddr string, sslHosts string,
certFile string, keyFile string, maxOpen int, insecure bool) (err error) {
server.TrapSignal(func() {
err := rs.listener.Close()
rs.log.Error("error closing listener", "err", err)
})
// TODO: re-enable insecure mode once #2715 has been addressed
if insecure {
fmt.Println(
"Insecure mode is temporarily disabled, please locally generate an " +
"SSL certificate to test. Support will be re-enabled soon!",
)
// listener, err = tmserver.StartHTTPServer(
// listenAddr, handler, logger,
// tmserver.Config{MaxOpenConnections: maxOpen},
// )
// if err != nil {
// return
// }
} else {
if certFile != "" {
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
err = validateCertKeyFiles(certFile, keyFile)
if err != nil {
return err
}
// cert/key pair is provided, read the fingerprint
rs.fingerprint, err = fingerprintFromFile(certFile)
if err != nil {
return err
}
} else {
// if certificate is not supplied, generate a self-signed one
certFile, keyFile, rs.fingerprint, err = genCertKeyFilesAndReturnFingerprint(sslHosts)
if err != nil {
return err
}
defer func() {
os.Remove(certFile)
os.Remove(keyFile)
}()
}
rs.listener, err = tmserver.StartHTTPAndTLSServer(
listenAddr, rs.Mux,
certFile, keyFile,
rs.log,
tmserver.Config{MaxOpenConnections: maxOpen},
)
if err != nil {
return
}
rs.log.Info(rs.fingerprint)
rs.log.Info("REST server started")
}
// logger.Info("REST server started")
return nil
}
// ServeCommand will generate a long-running rest server // ServeCommand will generate a long-running rest server
// (aka Light Client Daemon) that exposes functionality similar // (aka Light Client Daemon) that exposes functionality similar
// to the cli, but over rest // to the cli, but over rest
func ServeCommand(cdc *codec.Codec) *cobra.Command { func (rs *RestServer) ServeCommand() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "rest-server", Use: "rest-server",
Short: "Start LCD (light-client daemon), a local REST server", Short: "Start LCD (light-client daemon), a local REST server",
RunE: func(cmd *cobra.Command, args []string) (err error) { RunE: func(cmd *cobra.Command, args []string) (err error) {
listenAddr := viper.GetString(flagListenAddr) rs.setKeybase(nil)
handler := createHandler(cdc) // Start the rest server and return error if one exists
err = rs.Start(
viper.GetString(client.FlagListenAddr),
viper.GetString(client.FlagSSLHosts),
viper.GetString(client.FlagSSLCertFile),
viper.GetString(client.FlagSSLKeyFile),
viper.GetInt(client.FlagMaxOpenConnections),
viper.GetBool(client.FlagInsecure))
registerSwaggerUI(handler) return err
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
maxOpen := viper.GetInt(flagMaxOpenConnections)
sslHosts := viper.GetString(flagSSLHosts)
certFile := viper.GetString(flagSSLCertFile)
keyFile := viper.GetString(flagSSLKeyFile)
var listener net.Listener
var fingerprint string
server.TrapSignal(func() {
err := listener.Close()
logger.Error("error closing listener", "err", err)
})
var cleanupFunc func()
// TODO: re-enable insecure mode once #2715 has been addressed
if viper.GetBool(flagInsecure) {
fmt.Println(
"Insecure mode is temporarily disabled, please locally generate an " +
"SSL certificate to test. Support will be re-enabled soon!",
)
// listener, err = tmserver.StartHTTPServer(
// listenAddr, handler, logger,
// tmserver.Config{MaxOpenConnections: maxOpen},
// )
// if err != nil {
// return
// }
} else {
if certFile != "" {
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
err = validateCertKeyFiles(certFile, keyFile)
if err != nil {
return err
}
// cert/key pair is provided, read the fingerprint
fingerprint, err = fingerprintFromFile(certFile)
if err != nil {
return err
}
} else {
// if certificate is not supplied, generate a self-signed one
certFile, keyFile, fingerprint, err = genCertKeyFilesAndReturnFingerprint(sslHosts)
if err != nil {
return err
}
cleanupFunc = func() {
os.Remove(certFile)
os.Remove(keyFile)
}
defer cleanupFunc()
}
listener, err = tmserver.StartHTTPAndTLSServer(
listenAddr, handler,
certFile, keyFile,
logger,
tmserver.Config{MaxOpenConnections: maxOpen},
)
if err != nil {
return
}
logger.Info(fingerprint)
logger.Info("REST server started")
}
// logger.Info("REST server started")
return nil
}, },
} }
cmd.Flags().String(flagListenAddr, "tcp://localhost:1317", "The address for the server to listen on") client.RegisterRestServerFlags(cmd)
cmd.Flags().Bool(flagInsecure, false, "Do not set up SSL/TLS layer")
cmd.Flags().String(flagSSLHosts, "", "Comma-separated hostnames and IPs to generate a certificate for")
cmd.Flags().String(flagSSLCertFile, "", "Path to a SSL certificate file. If not supplied, a self-signed certificate will be generated.")
cmd.Flags().String(flagSSLKeyFile, "", "Path to a key file; ignored if a certificate file is not supplied.")
cmd.Flags().String(flagCORS, "", "Set the domains that can make CORS requests (* for all)")
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
cmd.Flags().String(client.FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(client.FlagIndentResponse, false, "Add indent to JSON response")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
return cmd return cmd
} }
func createHandler(cdc *codec.Codec) *mux.Router { func (rs *RestServer) registerSwaggerUI() {
r := mux.NewRouter()
kb, err := keys.GetKeyBase() //XXX
if err != nil {
panic(err)
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
// TODO: make more functional? aka r = keys.RegisterRoutes(r)
r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET")
r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET")
keys.RegisterRoutes(r, cliCtx.Indent)
rpc.RegisterRoutes(cliCtx, r)
tx.RegisterRoutes(cliCtx, r, cdc)
auth.RegisterRoutes(cliCtx, r, cdc, "acc")
bank.RegisterRoutes(cliCtx, r, cdc, kb)
stake.RegisterRoutes(cliCtx, r, cdc, kb)
slashing.RegisterRoutes(cliCtx, r, cdc, kb)
gov.RegisterRoutes(cliCtx, r, cdc)
return r
}
func registerSwaggerUI(r *mux.Router) {
statikFS, err := fs.New() statikFS, err := fs.New()
if err != nil { if err != nil {
panic(err) panic(err)
} }
staticServer := http.FileServer(statikFS) staticServer := http.FileServer(statikFS)
r.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer)) rs.Mux.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer))
} }
func validateCertKeyFiles(certFile, keyFile string) error { func validateCertKeyFiles(certFile, keyFile string) error {

View File

@ -19,6 +19,8 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
gapp "github.com/cosmos/cosmos-sdk/cmd/gaia/app" gapp "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys" crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
@ -45,6 +47,12 @@ import (
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server" tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
authRest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankRest "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
govRest "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashingRest "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stakeRest "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
) )
// makePathname creates a unique pathname for each test. It will panic if it // makePathname creates a unique pathname for each test. It will panic if it
@ -103,6 +111,13 @@ func GetKeyBase(t *testing.T) crkeys.Keybase {
return keybase return keybase
} }
// GetTestKeyBase fetches the current testing keybase
func GetTestKeyBase(t *testing.T) crkeys.Keybase {
keybase, err := keys.GetKeyBaseWithWritePerm()
require.NoError(t, err)
return keybase
}
// CreateAddr adds an address to the key store and returns an address and seed. // CreateAddr adds an address to the key store and returns an address and seed.
// It also requires that the key could be created. // It also requires that the key could be created.
func CreateAddr(t *testing.T, name, password string, kb crkeys.Keybase) (sdk.AccAddress, string) { func CreateAddr(t *testing.T, name, password string, kb crkeys.Keybase) (sdk.AccAddress, string) {
@ -288,7 +303,7 @@ func InitializeTestLCD(
require.NoError(t, err) require.NoError(t, err)
tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress)) tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress))
lcd, err := startLCD(logger, listenAddr, cdc) lcd, err := startLCD(logger, listenAddr, cdc, t)
require.NoError(t, err) require.NoError(t, err)
tests.WaitForLCDStart(port) tests.WaitForLCDStart(port)
@ -347,8 +362,23 @@ func startTM(
// startLCD starts the LCD. // startLCD starts the LCD.
// //
// NOTE: This causes the thread to block. // NOTE: This causes the thread to block.
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec) (net.Listener, error) { func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec, t *testing.T) (net.Listener, error) {
return tmrpc.StartHTTPServer(listenAddr, createHandler(cdc), logger, tmrpc.Config{}) rs := NewRestServer(cdc)
rs.setKeybase(GetTestKeyBase(t))
registerRoutes(rs)
return tmrpc.StartHTTPServer(listenAddr, rs.Mux, logger, tmrpc.Config{})
}
// NOTE: If making updates here also update cmd/gaia/cmd/gaiacli/main.go
func registerRoutes(rs *RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
authRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, "acc")
bankRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stakeRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashingRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
govRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
} }
// Request makes a test LCD test request. It returns a response object and a // Request makes a test LCD test request. It returns a response object and a

View File

@ -1,9 +1,11 @@
package main package main
import ( import (
"net/http"
"os" "os"
"path" "path"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -13,9 +15,15 @@ import (
"github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/lcd" "github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/version"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik" _ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
) )
@ -37,15 +45,25 @@ var (
) )
func main() { func main() {
// Configure cobra to sort commands
cobra.EnableCommandSorting = false cobra.EnableCommandSorting = false
// Instantiate the codec for the command line application
cdc := app.MakeCodec() cdc := app.MakeCodec()
// Read in the configuration file for the sdk
config := sdk.GetConfig() config := sdk.GetConfig()
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub) config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub) config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
config.Seal() config.Seal()
// Create a new RestServer instance to serve the light client routes
rs := lcd.NewRestServer(cdc)
// registerRoutes registers the routes on the rest server
registerRoutes(rs)
// TODO: setup keybase, viper object, etc. to be passed into // TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do // the below functions and eliminate global vars, like we do
// with the cdc // with the cdc
@ -58,7 +76,7 @@ func main() {
queryCmd(cdc), queryCmd(cdc),
txCmd(cdc), txCmd(cdc),
client.LineBreak, client.LineBreak,
lcd.ServeCommand(cdc), rs.ServeCommand(),
client.LineBreak, client.LineBreak,
keys.Commands(), keys.Commands(),
client.LineBreak, client.LineBreak,
@ -79,6 +97,30 @@ func main() {
} }
} }
// registerRoutes registers the routes from the different modules for the LCD.
// NOTE: details on the routes added for each module are in the module documentation
// NOTE: If making updates here you also need to update the test helper in client/lcd/test_helper.go
func registerRoutes(rs *lcd.RestServer) {
registerSwaggerUI(rs)
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, "acc")
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stake.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
gov.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
}
func registerSwaggerUI(rs *lcd.RestServer) {
statikFS, err := fs.New()
if err != nil {
panic(err)
}
staticServer := http.FileServer(statikFS)
rs.Mux.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer))
}
func initConfig(cmd *cobra.Command) error { func initConfig(cmd *cobra.Command) error {
home, err := cmd.PersistentFlags().GetString(cli.HomeFlag) home, err := cmd.PersistentFlags().GetString(cli.HomeFlag)
if err != nil { if err != nil {

View File

@ -9,12 +9,17 @@ import (
"github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/docs/examples/basecoin/app" "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/app"
"github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types" "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli" stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/cli"
) )
@ -34,6 +39,17 @@ func main() {
// get the codec // get the codec
cdc := app.MakeCodec() cdc := app.MakeCodec()
// Setup certain SDK config
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("baseacc", "basepub")
config.SetBech32PrefixForValidator("baseval", "basevalpub")
config.SetBech32PrefixForConsensusNode("basecons", "baseconspub")
config.Seal()
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
// TODO: Setup keybase, viper object, etc. to be passed into // TODO: Setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do // the below functions and eliminate global vars, like we do
// with the cdc. // with the cdc.
@ -83,7 +99,7 @@ func main() {
// add proxy, version and key info // add proxy, version and key info
rootCmd.AddCommand( rootCmd.AddCommand(
client.LineBreak, client.LineBreak,
lcd.ServeCommand(cdc), rs.ServeCommand(),
keys.Commands(), keys.Commands(),
client.LineBreak, client.LineBreak,
version.VersionCmd, version.VersionCmd,
@ -97,3 +113,13 @@ func main() {
panic(err) panic(err)
} }
} }
func registerRoutes(rs *lcd.RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, "acc")
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stake.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
}

View File

@ -13,8 +13,9 @@ import (
"github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/app" "github.com/cosmos/cosmos-sdk/docs/examples/democoin/app"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/types" "github.com/cosmos/cosmos-sdk/docs/examples/democoin/types"
@ -47,6 +48,10 @@ func main() {
config.SetBech32PrefixForConsensusNode("democons", "democonspub") config.SetBech32PrefixForConsensusNode("democons", "democonspub")
config.Seal() config.Seal()
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
// TODO: setup keybase, viper object, etc. to be passed into // TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do // the below functions and eliminate global vars, like we do
// with the cdc // with the cdc
@ -74,11 +79,6 @@ func main() {
)...) )...)
rootCmd.AddCommand( rootCmd.AddCommand(
client.PostCommands( client.PostCommands(
ibccmd.IBCTransferCmd(cdc),
)...)
rootCmd.AddCommand(
client.PostCommands(
ibccmd.IBCRelayCmd(cdc),
simplestakingcmd.BondTxCmd(cdc), simplestakingcmd.BondTxCmd(cdc),
)...) )...)
rootCmd.AddCommand( rootCmd.AddCommand(
@ -96,7 +96,7 @@ func main() {
// add proxy, version and key info // add proxy, version and key info
rootCmd.AddCommand( rootCmd.AddCommand(
client.LineBreak, client.LineBreak,
lcd.ServeCommand(cdc), rs.ServeCommand(),
keys.Commands(), keys.Commands(),
client.LineBreak, client.LineBreak,
version.VersionCmd, version.VersionCmd,
@ -110,3 +110,11 @@ func main() {
panic(err) panic(err)
} }
} }
func registerRoutes(rs *lcd.RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, "acc")
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
}