diff --git a/PENDING.md b/PENDING.md index ed15ac7f8..f0dfe58aa 100644 --- a/PENDING.md +++ b/PENDING.md @@ -88,7 +88,7 @@ FEATURES * [gaia-lite] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions * [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`. * [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint. - * [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers` + * [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}` * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params diff --git a/client/keys/add.go b/client/keys/add.go index be2825a55..29ed3e456 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -8,7 +8,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/gorilla/mux" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -61,7 +60,7 @@ func runAddCmd(cmd *cobra.Command, args []string) error { name = "inmemorykey" } else { if len(args) != 1 || len(args[0]) == 0 { - return errors.New("you must provide a name for the key") + return errMissingName() } name = args[0] kb, err = GetKeyBase() @@ -144,11 +143,16 @@ func printCreate(info keys.Info, seed string) { if !viper.GetBool(flagNoBackup) { out.Seed = seed } - json, err := MarshalJSON(out) + var jsonString []byte + if viper.GetBool(client.FlagIndentResponse) { + jsonString, err = cdc.MarshalJSONIndent(out, "", " ") + } else { + jsonString, err = cdc.MarshalJSON(out) + } if err != nil { panic(err) // really shouldn't happen... } - fmt.Println(string(json)) + fmt.Println(string(jsonString)) default: panic(fmt.Sprintf("I can't speak: %s", output)) } @@ -165,77 +169,78 @@ type NewKeyBody struct { } // add new key REST handler -func AddNewKeyRequestHandler(w http.ResponseWriter, r *http.Request) { - var kb keys.Keybase - var m NewKeyBody +func AddNewKeyRequestHandler(indent bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var kb keys.Keybase + var m NewKeyBody - kb, err := GetKeyBase() - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - - body, err := ioutil.ReadAll(r.Body) - err = json.Unmarshal(body, &m) - - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - if m.Name == "" { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("You have to specify a name for the locally stored account.")) - return - } - if m.Password == "" { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("You have to specify a password for the locally stored account.")) - return - } - - // check if already exists - infos, err := kb.List() - for _, i := range infos { - if i.GetName() == m.Name { - w.WriteHeader(http.StatusConflict) - w.Write([]byte(fmt.Sprintf("Account with name %s already exists.", m.Name))) + kb, err := GetKeyBase() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) return } - } - // create account - seed := m.Seed - if seed == "" { - seed = getSeed(keys.Secp256k1) - } - info, err := kb.CreateKey(m.Name, seed, m.Password) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return - } + body, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + err = json.Unmarshal(body, &m) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + if m.Name == "" { + w.WriteHeader(http.StatusBadRequest) + err = errMissingName() + w.Write([]byte(err.Error())) + return + } + if m.Password == "" { + w.WriteHeader(http.StatusBadRequest) + err = errMissingPassword() + w.Write([]byte(err.Error())) + return + } - keyOutput, err := Bech32KeyOutput(info) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return + // check if already exists + infos, err := kb.List() + for _, info := range infos { + if info.GetName() == m.Name { + w.WriteHeader(http.StatusConflict) + err = errKeyNameConflict(m.Name) + w.Write([]byte(err.Error())) + return + } + } + + // create account + seed := m.Seed + if seed == "" { + seed = getSeed(keys.Secp256k1) + } + info, err := kb.CreateKey(m.Name, seed, m.Password) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + keyOutput, err := Bech32KeyOutput(info) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + keyOutput.Seed = seed + + PostProcessResponse(w, cdc, keyOutput, indent) } - - keyOutput.Seed = seed - - bz, err := json.Marshal(keyOutput) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return - } - - w.Write(bz) } - // function to just a new seed to display in the UI before actually persisting it in the keybase func getSeed(algo keys.SigningAlgo) string { kb := client.MockKeyBase() @@ -258,3 +263,82 @@ func SeedRequestHandler(w http.ResponseWriter, r *http.Request) { seed := getSeed(algo) w.Write([]byte(seed)) } + +// RecoverKeyBody is recover key request REST body +type RecoverKeyBody struct { + Password string `json:"password"` + Seed string `json:"seed"` +} + +// RecoverRequestHandler performs key recover request +func RecoverRequestHandler(indent bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name := vars["name"] + var m RecoverKeyBody + body, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + err = cdc.UnmarshalJSON(body, &m) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + if name == "" { + w.WriteHeader(http.StatusBadRequest) + err = errMissingName() + w.Write([]byte(err.Error())) + return + } + if m.Password == "" { + w.WriteHeader(http.StatusBadRequest) + err = errMissingPassword() + w.Write([]byte(err.Error())) + return + } + if m.Seed == "" { + w.WriteHeader(http.StatusBadRequest) + err = errMissingSeed() + w.Write([]byte(err.Error())) + return + } + + kb, err := GetKeyBase() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + // check if already exists + infos, err := kb.List() + for _, info := range infos { + if info.GetName() == name { + w.WriteHeader(http.StatusConflict) + err = errKeyNameConflict(name) + w.Write([]byte(err.Error())) + return + } + } + + info, err := kb.CreateKey(name, m.Seed, m.Password) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + keyOutput, err := Bech32KeyOutput(info) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + PostProcessResponse(w, cdc, keyOutput, indent) + } +} \ No newline at end of file diff --git a/client/keys/delete.go b/client/keys/delete.go index 944feb4b1..23fc41ffd 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -68,14 +68,14 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) err := decoder.Decode(&m) if err != nil { - w.WriteHeader(400) + w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } kb, err = GetKeyBase() if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } @@ -83,10 +83,10 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) { // TODO handle error if key is not available or pass is wrong err = kb.Delete(name, m.Password) if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } diff --git a/client/keys/errors.go b/client/keys/errors.go new file mode 100644 index 000000000..2689a918f --- /dev/null +++ b/client/keys/errors.go @@ -0,0 +1,19 @@ +package keys + +import "fmt" + +func errKeyNameConflict(name string) error { + return fmt.Errorf("acount with name %s already exists", name) +} + +func errMissingName() error { + return fmt.Errorf("you have to specify a name for the locally stored account") +} + +func errMissingPassword() error { + return fmt.Errorf("you have to specify a password for the locally stored account") +} + +func errMissingSeed() error { + return fmt.Errorf("you have to specify seed for key recover") +} \ No newline at end of file diff --git a/client/keys/list.go b/client/keys/list.go index 22f163f1d..f232fccff 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -1,7 +1,6 @@ package keys import ( - "encoding/json" "net/http" "github.com/spf13/cobra" @@ -35,35 +34,31 @@ func runListCmd(cmd *cobra.Command, args []string) error { // REST // query key list REST handler -func QueryKeysRequestHandler(w http.ResponseWriter, r *http.Request) { - kb, err := GetKeyBase() - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return +func QueryKeysRequestHandler(indent bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + kb, err := GetKeyBase() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + infos, err := kb.List() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + // an empty list will be JSONized as null, but we want to keep the empty list + if len(infos) == 0 { + PostProcessResponse(w, cdc, "[]", indent) + return + } + keysOutput, err := Bech32KeysOutput(infos) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + PostProcessResponse(w, cdc, keysOutput, indent) } - infos, err := kb.List() - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - // an empty list will be JSONized as null, but we want to keep the empty list - if len(infos) == 0 { - w.Write([]byte("[]")) - return - } - keysOutput, err := Bech32KeysOutput(infos) - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - output, err := json.MarshalIndent(keysOutput, "", " ") - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - w.Write(output) } diff --git a/client/keys/root.go b/client/keys/root.go index f2a27dc0c..a7a7d2e6f 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -30,11 +30,12 @@ func Commands() *cobra.Command { } // resgister REST routes -func RegisterRoutes(r *mux.Router) { - r.HandleFunc("/keys", QueryKeysRequestHandler).Methods("GET") - r.HandleFunc("/keys", AddNewKeyRequestHandler).Methods("POST") +func RegisterRoutes(r *mux.Router, indent bool) { + r.HandleFunc("/keys", QueryKeysRequestHandler(indent)).Methods("GET") + r.HandleFunc("/keys", AddNewKeyRequestHandler(indent)).Methods("POST") r.HandleFunc("/keys/seed", SeedRequestHandler).Methods("GET") - r.HandleFunc("/keys/{name}", GetKeyRequestHandler).Methods("GET") + r.HandleFunc("/keys/{name}/recover", RecoverRequestHandler(indent)).Methods("POST") + r.HandleFunc("/keys/{name}", GetKeyRequestHandler(indent)).Methods("GET") r.HandleFunc("/keys/{name}", UpdateKeyRequestHandler).Methods("PUT") r.HandleFunc("/keys/{name}", DeleteKeyRequestHandler).Methods("DELETE") } diff --git a/client/keys/show.go b/client/keys/show.go index 82c6f9883..b567daf12 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -1,7 +1,6 @@ package keys import ( - "encoding/json" "fmt" "net/http" @@ -91,44 +90,39 @@ func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { // REST // get key REST handler -func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - name := vars["name"] - bechPrefix := r.URL.Query().Get(FlagBechPrefix) +func GetKeyRequestHandler(indent bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name := vars["name"] + bechPrefix := r.URL.Query().Get(FlagBechPrefix) - if bechPrefix == "" { - bechPrefix = "acc" + if bechPrefix == "" { + bechPrefix = "acc" + } + + bechKeyOut, err := getBechKeyOut(bechPrefix) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + info, err := GetKeyInfo(name) + // TODO: check for the error if key actually does not exist, instead of + // assuming this as the reason + if err != nil { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(err.Error())) + return + } + + keyOutput, err := bechKeyOut(info) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + PostProcessResponse(w, cdc, keyOutput, indent) } - - bechKeyOut, err := getBechKeyOut(bechPrefix) - if err != nil { - w.WriteHeader(400) - w.Write([]byte(err.Error())) - return - } - - info, err := GetKeyInfo(name) - // TODO: check for the error if key actually does not exist, instead of - // assuming this as the reason - if err != nil { - w.WriteHeader(404) - w.Write([]byte(err.Error())) - return - } - - keyOutput, err := bechKeyOut(info) - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - - output, err := json.MarshalIndent(keyOutput, "", " ") - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - return - } - - w.Write(output) } diff --git a/client/keys/update.go b/client/keys/update.go index 78a81bf0e..18a18be58 100644 --- a/client/keys/update.go +++ b/client/keys/update.go @@ -69,14 +69,14 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) err := decoder.Decode(&m) if err != nil { - w.WriteHeader(400) + w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } kb, err = GetKeyBase() if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } @@ -86,10 +86,10 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) { // TODO check if account exists and if password is correct err = kb.Update(name, m.OldPassword, getNewpass) if err != nil { - w.WriteHeader(401) + w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(err.Error())) return } - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } diff --git a/client/keys/utils.go b/client/keys/utils.go index 95fc83ed6..a4fa867eb 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -13,6 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" + "net/http" + "github.com/cosmos/cosmos-sdk/codec" ) // KeyDBName is the directory under root where we store the keys @@ -231,3 +233,26 @@ func printPubKey(info keys.Info, bechKeyOut bechKeyOutFn) { fmt.Println(ko.PubKey) } + +// PostProcessResponse performs post process for rest response +func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response interface{}, indent bool) { + var output []byte + switch response.(type) { + default: + var err error + if indent { + output, err = cdc.MarshalJSONIndent(response, "", " ") + } else { + output, err = cdc.MarshalJSON(response) + } + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + case []byte: + output = response.([]byte) + } + w.Header().Set("Content-Type", "application/json") + w.Write(output) +} diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 485c5a2f6..1c3c93658 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -54,9 +54,13 @@ func TestKeys(t *testing.T) { match := reg.MatchString(seed) require.True(t, match, "Returned seed has wrong format", seed) + // recover key + recoverName := "test_recovername" + recoverPassword := "1234567890" + doRecoverKey(t, port, recoverName, recoverPassword, seed) + newName := "test_newname" newPassword := "0987654321" - // add key jsonStr := []byte(fmt.Sprintf(`{"name":"%s", "password":"%s", "seed":"%s"}`, newName, newPassword, seed)) res, body = Request(t, port, "POST", "/keys", jsonStr) @@ -78,7 +82,7 @@ func TestKeys(t *testing.T) { // existing keys res, body = Request(t, port, "GET", "/keys", nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var m [2]keys.KeyOutput + var m [3]keys.KeyOutput err = cdc.UnmarshalJSON([]byte(body), &m) require.Nil(t, err) @@ -243,7 +247,7 @@ func TestCoinSend(t *testing.T) { someFakeAddr := sdk.AccAddress(bz) // query empty - res, body := Request(t, port, "GET", fmt.Sprintf("/accounts/%s", someFakeAddr), nil) + res, body := Request(t, port, "GET", fmt.Sprintf("/auth/accounts/%s", someFakeAddr), nil) require.Equal(t, http.StatusNoContent, res.StatusCode, body) acc := getAccount(t, port, addr) @@ -802,7 +806,7 @@ func TestProposalsQuery(t *testing.T) { //_____________________________________________________________________________ // get the account to get the sequence func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account { - res, body := Request(t, port, "GET", fmt.Sprintf("/accounts/%s", addr), nil) + res, body := Request(t, port, "GET", fmt.Sprintf("/auth/accounts/%s", addr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var acc auth.Account err := cdc.UnmarshalJSON([]byte(body), &acc) @@ -856,6 +860,20 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc return } +func doRecoverKey(t *testing.T, port, recoverName, recoverPassword, seed string) { + jsonStr := []byte(fmt.Sprintf(`{"password":"%s", "seed":"%s"}`, recoverPassword, seed)) + res, body := Request(t, port, "POST", fmt.Sprintf("/keys/%s/recover", recoverName), jsonStr) + + require.Equal(t, http.StatusOK, res.StatusCode, body) + var resp keys.KeyOutput + err := codec.Cdc.UnmarshalJSON([]byte(body), &resp) + require.Nil(t, err, body) + + addr1Bech32 := resp.Address + _, err = sdk.AccAddressFromBech32(addr1Bech32) + require.NoError(t, err, "Failed to return a correct bech32 address") +} + func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, "", 0, "") require.Equal(t, http.StatusOK, res.StatusCode, body) diff --git a/client/lcd/root.go b/client/lcd/root.go index ef690ed55..475186ed0 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -145,7 +145,7 @@ func createHandler(cdc *codec.Codec) *mux.Router { r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET") r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET") - keys.RegisterRoutes(r) + keys.RegisterRoutes(r, cliCtx.Indent) rpc.RegisterRoutes(cliCtx, r) tx.RegisterRoutes(cliCtx, r, cdc) auth.RegisterRoutes(cliCtx, r, cdc, "acc") diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index 9c4246394..b7fb70ff3 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -346,6 +346,184 @@ paths: $ref: "#/definitions/BroadcastTxCommitResult" 400: description: The Tx was malformated + /keys: + get: + summary: List of accounts stored locally + tags: + - ICS1 + produces: + - application/json + responses: + 200: + description: Array of accounts + schema: + type: array + items: + $ref: '#/definitions/Account' + post: + summary: Create a new account locally + tags: + - ICS1 + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: account + description: The account to create + schema: + type: object + required: + - name + - password + - seed + properties: + name: + type: string + password: + type: string + seed: + type: string + responses: + 200: + description: Returns account information of the created key + schema: + $ref: "#/definitions/Account" + /keys/seed: + get: + summary: Create a new seed to create a new account with + tags: + - ICS1 + responses: + 200: + description: 16 word Seed + schema: + type: string + /keys/{name}/recover: + post: + summary: Recover a account from a seed + tags: + - ICS1 + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: name + description: Account name + required: true + type: string + - in: body + name: pwdAndSeed + description: Provide password and seed to recover a key + schema: + type: object + required: + - password + - seed + properties: + password: + type: string + seed: + type: string + responses: + 200: + description: Returns account information of the recovered key + schema: + $ref: "#/definitions/Account" + /keys/{name}: + parameters: + - in: path + name: name + description: Account name + required: true + type: string + get: + summary: Get a certain locally stored account + tags: + - ICS1 + produces: + - application/json + responses: + 200: + description: Locally stored account + schema: + $ref: "#/definitions/Account" + 404: + description: Account is not available + put: + summary: Update the password for this account in the KMS + tags: + - ICS1 + consumes: + - application/json + parameters: + - in: body + name: account + description: The new and old password + schema: + type: object + required: + - new_password + - old_password + properties: + new_password: + type: string + old_password: + type: string + responses: + 200: + description: Updated password + 401: + description: Password is wrong + 404: + description: Account is not available + delete: + summary: Remove an account + tags: + - ICS1 + consumes: + - application/json + parameters: + - in: body + name: account + description: The password of the account to remove from the KMS + schema: + type: object + required: + - password + properties: + password: + type: string + responses: + 200: + description: Removed account + 401: + description: Password is wrong + 404: + description: Account is not available + /auth/accounts/{address}: + get: + summary: Get the account information on blockchain + tags: + - ICS1 + produces: + - application/json + parameters: + - in: path + name: address + description: Account address + required: true + type: string + responses: + 200: + description: Account information on the blockchain + schema: + $ref: "#/definitions/AccountQueryResponse" + 404: + description: Account is not available definitions: CheckTxResult: @@ -561,7 +739,35 @@ definitions: address: $ref: "#/definitions/Address" pub_key: - $ref: "#/definitions/PubKey" + type: string + example: "cosmospub1addwnpepqfgv3pakxazq2fgs8tmmhmzsrs94fptl7kyztyxprjpf0mkus3h7cxqe70s" + type: + type: string + example: local + seed: + type: string + AccountInfo: + type: object + properties: + account_number: + type: string + address: + type: string + coins: + type: array + items: + $ref: "#/definitions/Coin" + public_key: + type: string + sequence: + type: string + AccountQueryResponse: + type: object + properties: + type: + type: string + value: + $ref: "#/definitions/AccountInfo" BlockID: type: object properties: diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index ccd3a4bf7..5d47eb692 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -17,7 +17,7 @@ import ( // register REST routes func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, storeName string) { r.HandleFunc( - "/accounts/{address}", + "/auth/accounts/{address}", QueryAccountRequestHandlerFn(storeName, cdc, authcmd.GetAccountDecoder(cdc), cliCtx), ).Methods("GET") r.HandleFunc( @@ -36,7 +36,6 @@ func QueryAccountRequestHandlerFn( decoder auth.AccountDecoder, cliCtx context.CLIContext, ) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") vars := mux.Vars(r) bech32addr := vars["address"]