From 92fdd1e9e6a9f8b57fd45fc607b3a1a98f32d591 Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Tue, 2 Apr 2019 23:57:01 +0800 Subject: [PATCH 01/10] gaiacli tx decode #3872 --- client/lcd/swagger-ui/swagger.yaml | 33 +++++++++ client/tx/decode.go | 105 +++++++++++++++++++++++++++++ client/tx/root.go | 1 + client/utils/utils.go | 9 ++- cmd/gaia/cmd/gaiacli/main.go | 1 + 5 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 client/tx/decode.go diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index 8a0df1e318f8..ea55c4680c09 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -322,6 +322,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/client/tx/root.go b/client/tx/root.go index cb2c6460917e..84d10c0a945f 100644 --- a/client/tx/root.go +++ b/client/tx/root.go @@ -13,4 +13,5 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) r.HandleFunc("/txs", QueryTxsByTagsRequestHandlerFn(cliCtx, cdc)).Methods("GET") r.HandleFunc("/txs", BroadcastTxRequest(cliCtx, cdc)).Methods("POST") r.HandleFunc("/txs/encode", EncodeTxRequestHandlerFn(cdc, cliCtx)).Methods("POST") + r.HandleFunc("/txs/decode", DecodeTxRequestHandlerFn(cdc, cliCtx)).Methods("POST") } diff --git a/client/utils/utils.go b/client/utils/utils.go index 25d81c4518e4..16c00113a15c 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -158,9 +158,14 @@ func PrintUnsignedStdTx( return } - json, err := cliCtx.Codec.MarshalJSON(stdTx) + 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) + _, _ = fmt.Fprintf(cliCtx.Output, "%s\n", json) } return diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 4fd6d1c3ad75..718ed1a242f7 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -153,6 +153,7 @@ func txCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command { authcmd.GetMultiSignCommand(cdc), tx.GetBroadcastCommand(cdc), tx.GetEncodeCommand(cdc), + tx.GetDecodeCommand(cdc), client.LineBreak, ) From 6e413f332a05f735f69f3e16b326d5b36397f03f Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Wed, 3 Apr 2019 00:24:38 +0800 Subject: [PATCH 02/10] Modify Short usage and delete Long. --- client/tx/decode.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/tx/decode.go b/client/tx/decode.go index 6775afd0f926..13c48b2b6d7c 100644 --- a/client/tx/decode.go +++ b/client/tx/decode.go @@ -75,8 +75,7 @@ func (tx txDecodeRespTx) String() string { 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 ......`, + Short: "Decode an amino-encoded transaction string", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { cliCtx := context.NewCLIContext().WithCodec(codec) From ee5a94b9dee9030cc33b4caec410c00347e95d1a Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Wed, 3 Apr 2019 22:25:53 +0800 Subject: [PATCH 03/10] Add cli_test and lcd_test. --- client/lcd/lcd_test.go | 41 +++++++++++++++++++++++++++++++ cmd/gaia/cli_test/cli_test.go | 39 +++++++++++++++++++++++++++++ cmd/gaia/cli_test/test_helpers.go | 6 +++++ 3 files changed, 86 insertions(+) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 69c5281b38f3..fb74cfe1bba2 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -319,6 +319,47 @@ func TestEncodeTx(t *testing.T) { require.Equal(t, memo, decodedTx.Memo) } +func TestDecodeTx(t *testing.T) { + kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, "")) + require.NoError(t, err) + addr, seed := CreateAddr(t, name1, pw, kb) + cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true) + defer cleanup() + + res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, "2", 1, false, false, fees) + var tx auth.StdTx + _ = cdc.UnmarshalJSON([]byte(body), &tx) + + encodeReq := clienttx.EncodeReq{Tx: tx} + encodedJSON, _ := cdc.MarshalJSON(encodeReq) + res, body = Request(t, port, "POST", "/txs/encode", encodedJSON) + + // Make sure it came back ok, and that we can encode it back to the transaction + // 200 response. + require.Equal(t, http.StatusOK, res.StatusCode, body) + encodeResp := struct { + Tx string `json:"tx"` + }{} + + require.Nil(t, cdc.UnmarshalJSON([]byte(body), &encodeResp)) + + decodeReq := clienttx.DecodeReq{Tx: encodeResp.Tx} + encodedJSON, _ = cdc.MarshalJSON(decodeReq) + res, body = Request(t, port, "POST", "/txs/decode", encodedJSON) + + // Make sure it came back ok, and that we can decode it back to the transaction + // 200 response. + require.Equal(t, http.StatusOK, res.StatusCode, body) + decodeResp := struct { + Tx auth.StdTx `json:"tx"` + }{} + + require.Nil(t, cdc.UnmarshalJSON([]byte(body), &decodeResp)) + + // check that the transaction decodes as expected + require.Equal(t, memo, decodeResp.Tx.Memo) +} + func TestTxs(t *testing.T) { kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, "")) require.NoError(t, err) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 2cb0d2223918..3e7d232815ac 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -875,6 +875,45 @@ func TestGaiaCLIEncode(t *testing.T) { require.Equal(t, "deadbeef", decodedTx.Memo) } +func TestGaiaCLIDecode(t *testing.T) { + t.Parallel() + f := InitFixtures(t) + + // start gaiad server + proc := f.GDStart() + defer proc.Stop(false) + + // Build a testing transaction and write it to disk + barAddr := f.KeyAddress(keyBar) + keyAddr := f.KeyAddress(keyFoo) + + sendTokens := sdk.TokensFromTendermintPower(10) + success, stdout, stderr := f.TxSend(keyAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only", "--memo", "deadbeef") + require.True(t, success) + require.Empty(t, stderr) + + // Write it to disk + jsonTxFile := WriteToNewTempFile(t, stdout) + defer os.Remove(jsonTxFile.Name()) + + // Run the encode command, and trim the extras from the stdout capture + success, base64Encoded, _ := f.TxEncode(jsonTxFile.Name()) + require.True(t, success) + trimmedBase64 := strings.Trim(base64Encoded, "\"\n") + + // Run the decode command + success, stdout, stderr = f.TxDecode(trimmedBase64) + require.True(t, success) + require.Empty(t, stderr) + + // Check that the transaction decodes as epxceted + var decodedTx auth.StdTx + cdc := app.MakeCodec() + unsignedTx := "{\"type\": \"auth/StdTx\",\"value\": " + stdout + "}" + require.Nil(t, cdc.UnmarshalJSON([]byte(unsignedTx), &decodedTx)) + require.Equal(t, "deadbeef", decodedTx.Memo) +} + func TestGaiaCLIMultisignSortSignatures(t *testing.T) { t.Parallel() f := InitFixtures(t) diff --git a/cmd/gaia/cli_test/test_helpers.go b/cmd/gaia/cli_test/test_helpers.go index 1df5b93c9eb8..8f32ee22569c 100644 --- a/cmd/gaia/cli_test/test_helpers.go +++ b/cmd/gaia/cli_test/test_helpers.go @@ -337,6 +337,12 @@ func (f *Fixtures) TxEncode(fileName string, flags ...string) (bool, string, str return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), client.DefaultKeyPass) } +// TxDecode is gaiacli tx decode +func (f *Fixtures) TxDecode(tx string, flags ...string) (bool, string, string) { + cmd := fmt.Sprintf("../../../build/gaiacli tx decode %s %v", tx, f.Flags()) + return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass) +} + // TxMultisign is gaiacli tx multisign func (f *Fixtures) TxMultisign(fileName, name string, signaturesFiles []string, flags ...string) (bool, string, string) { From c7d536adaf1d704790c3d47a809c3f6cc0900ee3 Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Wed, 3 Apr 2019 22:44:48 +0800 Subject: [PATCH 04/10] add pendings --- .pending/features/gaiacli/3872-Add-gaiacli-tx- | 1 + .pending/features/gaiarest/3872-Add-POST-txs-de | 1 + 2 files changed, 2 insertions(+) create mode 100644 .pending/features/gaiacli/3872-Add-gaiacli-tx- create mode 100644 .pending/features/gaiarest/3872-Add-POST-txs-de diff --git a/.pending/features/gaiacli/3872-Add-gaiacli-tx- b/.pending/features/gaiacli/3872-Add-gaiacli-tx- new file mode 100644 index 000000000000..d80f97cbb140 --- /dev/null +++ b/.pending/features/gaiacli/3872-Add-gaiacli-tx- @@ -0,0 +1 @@ +#3872 Add `gaiacli tx decode` \ No newline at end of file diff --git a/.pending/features/gaiarest/3872-Add-POST-txs-de b/.pending/features/gaiarest/3872-Add-POST-txs-de new file mode 100644 index 000000000000..7b44e4ad71ef --- /dev/null +++ b/.pending/features/gaiarest/3872-Add-POST-txs-de @@ -0,0 +1 @@ +#3872 Add `POST /txs/decode` \ No newline at end of file From dbc825b2064a890ff964eb13425ca74d64809dac Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Wed, 3 Apr 2019 22:50:12 +0800 Subject: [PATCH 05/10] Refactor --- cmd/gaia/cli_test/cli_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 3e7d232815ac..c0710fb9fa32 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -907,11 +907,11 @@ func TestGaiaCLIDecode(t *testing.T) { require.Empty(t, stderr) // Check that the transaction decodes as epxceted - var decodedTx auth.StdTx + var stdTx auth.StdTx cdc := app.MakeCodec() - unsignedTx := "{\"type\": \"auth/StdTx\",\"value\": " + stdout + "}" - require.Nil(t, cdc.UnmarshalJSON([]byte(unsignedTx), &decodedTx)) - require.Equal(t, "deadbeef", decodedTx.Memo) + jsonTx := "{\"type\": \"auth/StdTx\",\"value\": " + stdout + "}" + require.Nil(t, cdc.UnmarshalJSON([]byte(jsonTx), &stdTx)) + require.Equal(t, "deadbeef", stdTx.Memo) } func TestGaiaCLIMultisignSortSignatures(t *testing.T) { From 54945ce314e4135f47a4466b58d8221bbfa4d8b7 Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Wed, 17 Apr 2019 23:27:14 +0800 Subject: [PATCH 06/10] app.DefaultKeyPass -> client.DefaultKeyPass & use f.GaiacliBinary --- cmd/gaia/cli_test/test_helpers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/gaia/cli_test/test_helpers.go b/cmd/gaia/cli_test/test_helpers.go index 8f32ee22569c..fa6f45f370d1 100644 --- a/cmd/gaia/cli_test/test_helpers.go +++ b/cmd/gaia/cli_test/test_helpers.go @@ -339,8 +339,8 @@ func (f *Fixtures) TxEncode(fileName string, flags ...string) (bool, string, str // TxDecode is gaiacli tx decode func (f *Fixtures) TxDecode(tx string, flags ...string) (bool, string, string) { - cmd := fmt.Sprintf("../../../build/gaiacli tx decode %s %v", tx, f.Flags()) - return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass) + cmd := fmt.Sprintf("%s tx decode %s %v", f.GaiacliBinary, tx, f.Flags()) + return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), client.DefaultKeyPass) } // TxMultisign is gaiacli tx multisign From 9d247d166608e06b15f4c017a4d40638ac0c5bf9 Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Thu, 18 Apr 2019 15:00:42 +0800 Subject: [PATCH 07/10] Change response to `auth.StdTx`. --- client/lcd/swagger-ui/swagger.yaml | 5 +---- client/tx/decode.go | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index ea55c4680c09..df3414cfcceb 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -347,10 +347,7 @@ paths: 200: description: The tx was successfully decoded schema: - type: object - properties: - tx: - $ref: "#/definitions/StdTx" + $ref: "#/definitions/StdTx" 400: description: The tx was malformated 500: diff --git a/client/tx/decode.go b/client/tx/decode.go index 13c48b2b6d7c..dbfc41ee5946 100644 --- a/client/tx/decode.go +++ b/client/tx/decode.go @@ -21,9 +21,7 @@ type ( } // DecodeResp defines a tx decoding response. - DecodeResp struct { - Tx auth.StdTx `json:"tx"` - } + DecodeResp auth.StdTx ) // DecodeTxRequestHandlerFn returns the decode tx REST handler. In particular, @@ -58,7 +56,7 @@ func DecodeTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http. return } - response := DecodeResp{Tx: stdTx} + response := DecodeResp(stdTx) rest.PostProcessResponse(w, cdc, response, cliCtx.Indent) } } From e1b0181644f37c6e416265ef4479554296b180c8 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Thu, 18 Apr 2019 21:02:57 +0800 Subject: [PATCH 08/10] Update .pending/features/gaiarest/3872-Add-POST-txs-de Co-Authored-By: yangyanqing --- .pending/features/gaiarest/3872-Add-POST-txs-de | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pending/features/gaiarest/3872-Add-POST-txs-de b/.pending/features/gaiarest/3872-Add-POST-txs-de index 7b44e4ad71ef..55f976eec6a5 100644 --- a/.pending/features/gaiarest/3872-Add-POST-txs-de +++ b/.pending/features/gaiarest/3872-Add-POST-txs-de @@ -1 +1 @@ -#3872 Add `POST /txs/decode` \ No newline at end of file +#3872 Implement a RESTful endpoint to decode txs via `POST /txs/decode` From 1adc895015500c097da0e7f3c810452b4caf3f28 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Thu, 18 Apr 2019 21:03:14 +0800 Subject: [PATCH 09/10] Update .pending/features/gaiacli/3872-Add-gaiacli-tx- Co-Authored-By: yangyanqing --- .pending/features/gaiacli/3872-Add-gaiacli-tx- | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pending/features/gaiacli/3872-Add-gaiacli-tx- b/.pending/features/gaiacli/3872-Add-gaiacli-tx- index d80f97cbb140..5e521f3c93e6 100644 --- a/.pending/features/gaiacli/3872-Add-gaiacli-tx- +++ b/.pending/features/gaiacli/3872-Add-gaiacli-tx- @@ -1 +1 @@ -#3872 Add `gaiacli tx decode` \ No newline at end of file +#3872 Implement a command to decode txs via `gaiacli tx decode` From 4ca84a50a9e7910d7509cf6b7471489ba8607e7b Mon Sep 17 00:00:00 2001 From: Frank Yang Date: Fri, 19 Apr 2019 11:39:33 +0800 Subject: [PATCH 10/10] Fix test fail. --- client/lcd/lcd_test.go | 13 ++++++------- cmd/gaia/cli_test/cli_test.go | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index fb74cfe1bba2..7525515678e7 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -344,20 +344,19 @@ func TestDecodeTx(t *testing.T) { require.Nil(t, cdc.UnmarshalJSON([]byte(body), &encodeResp)) decodeReq := clienttx.DecodeReq{Tx: encodeResp.Tx} - encodedJSON, _ = cdc.MarshalJSON(decodeReq) - res, body = Request(t, port, "POST", "/txs/decode", encodedJSON) + decodedJSON, _ := cdc.MarshalJSON(decodeReq) + res, body = Request(t, port, "POST", "/txs/decode", decodedJSON) // Make sure it came back ok, and that we can decode it back to the transaction // 200 response. require.Equal(t, http.StatusOK, res.StatusCode, body) - decodeResp := struct { - Tx auth.StdTx `json:"tx"` - }{} + decodeResp := auth.StdTx{} - require.Nil(t, cdc.UnmarshalJSON([]byte(body), &decodeResp)) + aminoJson := "{\"type\": \"auth/StdTx\",\"value\": " + body + "}" + require.Nil(t, cdc.UnmarshalJSON([]byte(aminoJson), &decodeResp)) // check that the transaction decodes as expected - require.Equal(t, memo, decodeResp.Tx.Memo) + require.Equal(t, memo, decodeResp.Memo) } func TestTxs(t *testing.T) { diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index c0710fb9fa32..3d12c115b51e 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -909,8 +909,8 @@ func TestGaiaCLIDecode(t *testing.T) { // Check that the transaction decodes as epxceted var stdTx auth.StdTx cdc := app.MakeCodec() - jsonTx := "{\"type\": \"auth/StdTx\",\"value\": " + stdout + "}" - require.Nil(t, cdc.UnmarshalJSON([]byte(jsonTx), &stdTx)) + aminoJson := "{\"type\": \"auth/StdTx\",\"value\": " + stdout + "}" + require.Nil(t, cdc.UnmarshalJSON([]byte(aminoJson), &stdTx)) require.Equal(t, "deadbeef", stdTx.Memo) }