Expose LCD router, allowing devs to register custom routes from their modules (#2836)
* Fixes #1081
This commit is contained in:
parent
15b6fa0959
commit
9676ce7d48
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue