diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index aed3bc8f49be..06099559dd8b 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -339,6 +339,39 @@ paths: description: The tx was malformated 500: description: Server internal error + /txs/decode: + post: + tags: + - ICS0 + summary: Decode a transaction from the Amino wire format + description: Decode a transaction (signed or not) from base64-encoded Amino serialized bytes to JSON + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: tx + description: The tx to decode + required: true + schema: + type: object + properties: + tx: + type: string + example: SvBiXe4KPqijYZoKFFHEzJ8c2HPAfv2EFUcIhx0yPagwEhTy0vPA+GGhCEslKXa4Af0uB+mfShoMCgVzdGFrZRIDMTAwEgQQwJoM + responses: + 200: + description: The tx was successfully decoded + schema: + type: object + properties: + tx: + $ref: "#/definitions/StdTx" + 400: + description: The tx was malformated + 500: + description: Server internal error /bank/balances/{address}: get: summary: Get the account balances diff --git a/client/tx/decode.go b/client/tx/decode.go new file mode 100644 index 000000000000..6775afd0f926 --- /dev/null +++ b/client/tx/decode.go @@ -0,0 +1,105 @@ +package tx + +import ( + "encoding/base64" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/spf13/cobra" + "github.com/tendermint/go-amino" + "io/ioutil" + "net/http" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/x/auth" +) + +type ( + // DecodeReq defines a tx decoding request. + DecodeReq struct { + Tx string `json:"tx"` + } + + // DecodeResp defines a tx decoding response. + DecodeResp struct { + Tx auth.StdTx `json:"tx"` + } +) + +// DecodeTxRequestHandlerFn returns the decode tx REST handler. In particular, +// it takes base64-decoded bytes, decodes it from the Amino wire protocol, +// and responds with a json-formatted transaction. +func DecodeTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req DecodeReq + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + err = cdc.UnmarshalJSON(body, &req) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + txBytes, err := base64.StdEncoding.DecodeString(req.Tx) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + var stdTx auth.StdTx + err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + response := DecodeResp{Tx: stdTx} + rest.PostProcessResponse(w, cdc, response, cliCtx.Indent) + } +} + +// txDecodeRespStr implements a simple Stringer wrapper for a decoded tx. +type txDecodeRespTx auth.StdTx + +func (tx txDecodeRespTx) String() string { + return tx.String() +} + +// GetDecodeCommand returns the decode command to take Amino-serialized bytes and turn it into +// a JSONified transaction +func GetDecodeCommand(codec *amino.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "decode [amino-byte-string]", + Short: "Decode amino byte string to transactions generated offline", + Long: `Decode ......`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + cliCtx := context.NewCLIContext().WithCodec(codec) + + txBytesBase64 := args[0] + + txBytes, err := base64.StdEncoding.DecodeString(txBytesBase64) + if err != nil { + return err + } + + var stdTx auth.StdTx + err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx) + if err != nil { + return err + } + + response := txDecodeRespTx(stdTx) + _ = cliCtx.PrintOutput(response) + + return nil + }, + } + + return client.PostCommands(cmd)[0] +} diff --git a/x/auth/client/utils/tx.go b/x/auth/client/utils/tx.go index 0a5646eb7b30..a29f9f4ea5d0 100644 --- a/x/auth/client/utils/tx.go +++ b/x/auth/client/utils/tx.go @@ -154,8 +154,14 @@ func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, m return err } - json, err := cliCtx.Codec.MarshalJSON(stdTx) - if err != nil { + var json []byte + if viper.GetBool(client.FlagIndentResponse) { + json, err = cliCtx.Codec.MarshalJSONIndent(stdTx, "", " ") + } else { + json, err = cliCtx.Codec.MarshalJSON(stdTx) + } + if err == nil { + _, _ = fmt.Fprintf(cliCtx.Output, "%s\n", json) return err }