feat: Add tx encode and decode endpoints (#13789)
* add grpc endpoint for encoding proto tx's
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
@@ -770,6 +771,143 @@ func (s IntegrationTestSuite) TestGetBlockWithTxs_GRPCGateway() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s IntegrationTestSuite) TestTxEncode_GRPC() {
|
||||
txBuilder := s.mkTxBuilder()
|
||||
protoTx, err := txBuilderToProtoTx(txBuilder)
|
||||
s.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *tx.TxEncodeRequest
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{"nil request", nil, true, "request cannot be nil"},
|
||||
{"empty request", &tx.TxEncodeRequest{}, true, "invalid empty tx"},
|
||||
{"valid request with tx bytes", &tx.TxEncodeRequest{Tx: protoTx}, false, ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
res, err := s.queryClient.TxEncode(context.Background(), tc.req)
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
s.Require().Empty(res)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(res.GetTxBytes())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestTxEncode_GRPCGateway() {
|
||||
val := s.network.Validators[0]
|
||||
txBuilder := s.mkTxBuilder()
|
||||
protoTx, err := txBuilderToProtoTx(txBuilder)
|
||||
s.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *tx.TxEncodeRequest
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{"empty request", &tx.TxEncodeRequest{}, true, "invalid empty tx"},
|
||||
{"valid request with tx bytes", &tx.TxEncodeRequest{Tx: protoTx}, false, ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
req, err := val.ClientCtx.Codec.MarshalJSON(tc.req)
|
||||
s.Require().NoError(err)
|
||||
|
||||
res, err := testutil.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/encode", val.APIAddress), "application/json", req)
|
||||
s.Require().NoError(err)
|
||||
if tc.expErr {
|
||||
s.Require().Contains(string(res), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s IntegrationTestSuite) TestTxDecode_GRPC() {
|
||||
val := s.network.Validators[0]
|
||||
txBuilder := s.mkTxBuilder()
|
||||
|
||||
encodedTx, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
s.Require().NoError(err)
|
||||
|
||||
invalidTxBytes := append(encodedTx, byte(0o00))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *tx.TxDecodeRequest
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{"nil request", nil, true, "request cannot be nil"},
|
||||
{"empty request", &tx.TxDecodeRequest{}, true, "invalid empty tx bytes"},
|
||||
{"invalid tx bytes", &tx.TxDecodeRequest{TxBytes: invalidTxBytes}, true, "tx parse error"},
|
||||
{"valid request with tx bytes", &tx.TxDecodeRequest{TxBytes: encodedTx}, false, ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
res, err := s.queryClient.TxDecode(context.Background(), tc.req)
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
s.Require().Empty(res)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(res.GetTx())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s IntegrationTestSuite) TestTxDecode_GRPCGateway() {
|
||||
val := s.network.Validators[0]
|
||||
txBuilder := s.mkTxBuilder()
|
||||
|
||||
txBytes, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
s.Require().NoError(err)
|
||||
|
||||
invalidTxBytes := append(txBytes, byte(0o00))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *tx.TxDecodeRequest
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{"empty request", &tx.TxDecodeRequest{}, true, "invalid empty tx bytes"},
|
||||
{"invalid tx bytes", &tx.TxDecodeRequest{TxBytes: invalidTxBytes}, true, "tx parse error"},
|
||||
{"valid request with tx_bytes", &tx.TxDecodeRequest{TxBytes: txBytes}, false, ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
req, err := val.ClientCtx.Codec.MarshalJSON(tc.req)
|
||||
s.Require().NoError(err)
|
||||
|
||||
res, err := testutil.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/decode", val.APIAddress), "application/json", req)
|
||||
s.Require().NoError(err)
|
||||
if tc.expErr {
|
||||
s.Require().Contains(string(res), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
@@ -816,8 +954,8 @@ type protoTxProvider interface {
|
||||
}
|
||||
|
||||
// txBuilderToProtoTx converts a txBuilder into a proto tx.Tx.
|
||||
// Deprecated: It's only used for testing the deprecated Simulate gRPC endpoint
|
||||
// using a proto Tx field.
|
||||
// Deprecated: It's used for testing the deprecated Simulate gRPC endpoint
|
||||
// using a proto Tx field and for testing the TxEncode endpoint.
|
||||
func txBuilderToProtoTx(txBuilder client.TxBuilder) (*tx.Tx, error) { // nolint
|
||||
protoProvider, ok := txBuilder.(protoTxProvider)
|
||||
if !ok {
|
||||
|
||||
Reference in New Issue
Block a user