Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API server #323

Merged
merged 22 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
635 changes: 635 additions & 0 deletions cmd/api.go

Large diffs are not rendered by default.

216 changes: 212 additions & 4 deletions cmd/chains.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import (
"path"
"strings"

"github.com/gorilla/mux"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/cosmos/relayer/helpers"
"github.com/cosmos/relayer/relayer"
)

Expand Down Expand Up @@ -149,7 +151,7 @@ $ %s ch e ibc-0 trusting-period 32h`, appName, appName)),
return err
}

return overWriteConfig(cmd, config)
return overWriteConfig(config)
},
}
return cmd
Expand All @@ -165,7 +167,7 @@ func chainsDeleteCmd() *cobra.Command {
$ %s chains delete ibc-0
$ %s ch d ibc-0`, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
return overWriteConfig(cmd, config.DeleteChain(args[0]))
return overWriteConfig(config.DeleteChain(args[0]))
},
}
return cmd
Expand Down Expand Up @@ -282,7 +284,7 @@ $ %s chains add --url http://relayer.com/ibc0.json
return err
}

return overWriteConfig(cmd, out)
return overWriteConfig(out)
},
}

Expand All @@ -304,7 +306,7 @@ $ %s ch ad testnet/chains/`, appName, appName)),
if out, err = filesAdd(args[0]); err != nil {
return err
}
return overWriteConfig(cmd, out)
return overWriteConfig(out)
},
}

Expand Down Expand Up @@ -476,3 +478,209 @@ func urlInputAdd(rawurl string) (cfg *Config, err error) {
}
return config, err
}

// API Handlers

// GetChainsHandler returns the configured chains in json format
func GetChainsHandler(w http.ResponseWriter, r *http.Request) {
helpers.SuccessJSONResponse(http.StatusOK, config.Chains, w)
}

// GetChainHandler returns the configured chains in json format
func GetChainHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chain, err := config.Chains.Get(vars["name"])
if err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}
helpers.SuccessJSONResponse(http.StatusOK, chain, w)
}

// GetChainStatusHandler returns the configured chains in json format
func GetChainStatusHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chain, err := config.Chains.Get(vars["name"])
if err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}
helpers.SuccessJSONResponse(http.StatusOK, chainStatusResponse{}.Populate(chain), w)
}

type chainStatusResponse struct {
Light bool `json:"light"`
Path bool `json:"path"`
Key bool `json:"key"`
Balance bool `json:"balance"`
}

func (cs chainStatusResponse) Populate(c *relayer.Chain) chainStatusResponse {
_, err := c.GetAddress()
if err == nil {
cs.Key = true
}

coins, err := c.QueryBalance(c.Key)
if err == nil && !coins.Empty() {
cs.Balance = true
}

_, err = c.GetLatestLightHeader()
if err == nil {
cs.Light = true
}

for _, pth := range config.Paths {
if pth.Src.ChainID == c.ChainID || pth.Dst.ChainID == c.ChainID {
cs.Path = true
}
}
return cs
}

type addChainRequest struct {
Key string `json:"key"`
RPCAddr string `json:"rpc-addr"`
AccountPrefix string `json:"account-prefix"`
GasAdjustment string `json:"gas-adjustment"`
GasPrices string `json:"gas-prices"`
TrustingPeriod string `json:"trusting-period"`
FilePath string `json:"file"`
URL string `json:"url"`
}

// PostChainHandler handles the route
func PostChainHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chainID := vars["name"]

var request addChainRequest
err := json.NewDecoder(r.Body).Decode(&request)
if err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}

if request.FilePath != "" && request.URL != "" {
helpers.WriteErrorResponse(http.StatusBadRequest, errMultipleAddFlags, w)
return
}

var out *Config
switch {
case request.FilePath != "":
if out, err = fileInputAdd(request.FilePath); err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}
case request.URL != "":
if out, err = urlInputAdd(request.URL); err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}
default:
if out, err = addChainByRequest(request, chainID); err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}
}

if err = validateConfig(out); err != nil {
helpers.WriteErrorResponse(http.StatusInternalServerError, err, w)
return
}

if err = overWriteConfig(out); err != nil {
helpers.WriteErrorResponse(http.StatusInternalServerError, err, w)
return
}
helpers.SuccessJSONResponse(http.StatusCreated, fmt.Sprintf("chain %s added successfully", chainID), w)
}

func addChainByRequest(request addChainRequest, chainID string) (cfg *Config, err error) {
c := &relayer.Chain{}

if c, err = c.Update("chain-id", chainID); err != nil {
return nil, err
}

if c, err = c.Update("key", request.Key); err != nil {
return nil, err
}

if c, err = c.Update("rpc-addr", request.RPCAddr); err != nil {
return nil, err
}

if c, err = c.Update("account-prefix", request.AccountPrefix); err != nil {
return nil, err
}

if c, err = c.Update("gas-adjustment", request.GasAdjustment); err != nil {
return nil, err
}

if c, err = c.Update("gas-prices", request.GasPrices); err != nil {
return nil, err
}

if c, err = c.Update("trusting-period", request.TrustingPeriod); err != nil {
return nil, err
}

if err = config.AddChain(c); err != nil {
return nil, err
}

return config, nil
}

type editChainRequest struct {
Key string `json:"key"`
Value string `json:"value"`
}

// PutChainHandler handles the route
func PutChainHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chain, err := config.Chains.Get(vars["name"])
if err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}

var request editChainRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}

c, err := chain.Update(request.Key, request.Value)
if err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}

if err = config.DeleteChain(vars["name"]).AddChain(c); err != nil {
helpers.WriteErrorResponse(http.StatusBadRequest, err, w)
return
}

if err = overWriteConfig(config); err != nil {
helpers.WriteErrorResponse(http.StatusInternalServerError, err, w)
return
}
helpers.SuccessJSONResponse(http.StatusOK, fmt.Sprintf("chain %s updated", vars["name"]), w)

}

// DeleteChainHandler handles the route
func DeleteChainHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
if err := overWriteConfig(config.DeleteChain(vars["name"])); err != nil {
helpers.WriteErrorResponse(http.StatusInternalServerError, err, w)
return
}
helpers.SuccessJSONResponse(http.StatusOK, fmt.Sprintf("chain %s deleted", vars["name"]), w)
}
15 changes: 6 additions & 9 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ $ %s config add-chains configs/chains`, appName)),
if out, err = cfgFilesAddChains(args[0]); err != nil {
return err
}
return overWriteConfig(cmd, out)
return overWriteConfig(out)
},
}

Expand All @@ -206,7 +206,7 @@ $ %s config add-paths configs/paths`, appName)),
if out, err = cfgFilesAddPaths(args[0]); err != nil {
return err
}
return overWriteConfig(cmd, out)
return overWriteConfig(out)
},
}

Expand Down Expand Up @@ -347,13 +347,15 @@ func defaultConfig() []byte {

// GlobalConfig describes any global relayer settings
type GlobalConfig struct {
APIListenPort string `yaml:"api-listen-addr" json:"api-listen-addr"`
Timeout string `yaml:"timeout" json:"timeout"`
LightCacheSize int `yaml:"light-cache-size" json:"light-cache-size"`
}

// newDefaultGlobalConfig returns a global config with defaults set
func newDefaultGlobalConfig() GlobalConfig {
return GlobalConfig{
APIListenPort: ":5183",
Timeout: "10s",
LightCacheSize: 20,
}
Expand Down Expand Up @@ -439,13 +441,8 @@ func initConfig(cmd *cobra.Command) error {
return nil
}

func overWriteConfig(cmd *cobra.Command, cfg *Config) error {
home, err := cmd.Flags().GetString(flags.FlagHome)
if err != nil {
return err
}

cfgPath := path.Join(home, "config", "config.yaml")
func overWriteConfig(cfg *Config) (err error) {
cfgPath := path.Join(homePath, "config", "config.yaml")
if _, err = os.Stat(cfgPath); err == nil {
viper.SetConfigFile(cfgPath)
if err = viper.ReadInConfig(); err == nil {
Expand Down
5 changes: 0 additions & 5 deletions cmd/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import (
"fmt"
)

func wrapInitFailed(err error) error {
return fmt.Errorf("init failed: %w", err)
}

func errKeyExists(name string) error {
return fmt.Errorf("a key with name %s already exists", name)
}
Expand All @@ -18,6 +14,5 @@ func errKeyDoesntExist(name string) error {
}

var (
errInitWrongFlags = errors.New("expected either (--hash/-x & --height) OR --url/-u OR --force/-f, none given")
errMultipleAddFlags = errors.New("expected either --file/-f OR --url/u, found multiple")
)
Loading