@@ -3,6 +3,7 @@ package cometbft
33import (
44 "context"
55 "fmt"
6+ "strings"
67
78 abci "github.com/cometbft/cometbft/abci/types"
89 abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1"
@@ -24,6 +25,8 @@ import (
2425 codectypes "github.com/cosmos/cosmos-sdk/codec/types"
2526 sdk "github.com/cosmos/cosmos-sdk/types"
2627 txtypes "github.com/cosmos/cosmos-sdk/types/tx"
28+ "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
29+ authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
2730)
2831
2932type appSimulator [T transaction.Tx ] interface {
@@ -50,51 +53,6 @@ func gRPCServiceRegistrar[T transaction.Tx](
5053 }
5154}
5255
53- // CometBFTAutoCLIDescriptor is the auto-generated CLI descriptor for the CometBFT service
54- var CometBFTAutoCLIDescriptor = & autocliv1.ServiceCommandDescriptor {
55- Service : cmtv1beta1 .Service_ServiceDesc .ServiceName ,
56- RpcCommandOptions : []* autocliv1.RpcCommandOptions {
57- {
58- RpcMethod : "GetNodeInfo" ,
59- Use : "node-info" ,
60- Short : "Query the current node info" ,
61- },
62- {
63- RpcMethod : "GetSyncing" ,
64- Use : "syncing" ,
65- Short : "Query node syncing status" ,
66- },
67- {
68- RpcMethod : "GetLatestBlock" ,
69- Use : "block-latest" ,
70- Short : "Query for the latest committed block" ,
71- },
72- {
73- RpcMethod : "GetBlockByHeight" ,
74- Use : "block-by-height <height>" ,
75- Short : "Query for a committed block by height" ,
76- Long : "Query for a specific committed block using the CometBFT RPC `block_by_height` method" ,
77- PositionalArgs : []* autocliv1.PositionalArgDescriptor {{ProtoField : "height" }},
78- },
79- {
80- RpcMethod : "GetLatestValidatorSet" ,
81- Use : "validator-set" ,
82- Alias : []string {"validator-set-latest" , "comet-validator-set" , "cometbft-validator-set" , "tendermint-validator-set" },
83- Short : "Query for the latest validator set" ,
84- },
85- {
86- RpcMethod : "GetValidatorSetByHeight" ,
87- Use : "validator-set-by-height <height>" ,
88- Short : "Query for a validator set by height" ,
89- PositionalArgs : []* autocliv1.PositionalArgDescriptor {{ProtoField : "height" }},
90- },
91- {
92- RpcMethod : "ABCIQuery" ,
93- Skip : true ,
94- },
95- },
96- }
97-
9856type txServer [T transaction.Tx ] struct {
9957 clientCtx client.Context
10058 txCodec transaction.Codec [T ]
@@ -112,8 +70,33 @@ func (t txServer[T]) GetBlockWithTxs(context.Context, *txtypes.GetBlockWithTxsRe
11270}
11371
11472// GetTx implements tx.ServiceServer.
115- func (t txServer [T ]) GetTx (context.Context , * txtypes.GetTxRequest ) (* txtypes.GetTxResponse , error ) {
116- return nil , status .Error (codes .Unimplemented , "not implemented" )
73+ func (t txServer [T ]) GetTx (ctx context.Context , req * txtypes.GetTxRequest ) (* txtypes.GetTxResponse , error ) {
74+ if req == nil {
75+ return nil , status .Error (codes .InvalidArgument , "request cannot be nil" )
76+ }
77+
78+ if len (req .Hash ) == 0 {
79+ return nil , status .Error (codes .InvalidArgument , "tx hash cannot be empty" )
80+ }
81+
82+ result , err := authtx .QueryTx (t .clientCtx , req .Hash )
83+ if err != nil {
84+ if strings .Contains (err .Error (), "not found" ) {
85+ return nil , status .Errorf (codes .NotFound , "tx not found: %s" , req .Hash )
86+ }
87+
88+ return nil , err
89+ }
90+
91+ protoTx , ok := result .Tx .GetCachedValue ().(* txtypes.Tx )
92+ if ! ok {
93+ return nil , status .Errorf (codes .Internal , "expected %T, got %T" , txtypes.Tx {}, result .Tx .GetCachedValue ())
94+ }
95+
96+ return & txtypes.GetTxResponse {
97+ Tx : protoTx ,
98+ TxResponse : result ,
99+ }, nil
117100}
118101
119102// GetTxsEvent implements tx.ServiceServer.
@@ -181,18 +164,79 @@ func (t txServer[T]) TxDecode(context.Context, *txtypes.TxDecodeRequest) (*txtyp
181164}
182165
183166// TxDecodeAmino implements tx.ServiceServer.
184- func (t txServer [T ]) TxDecodeAmino (context.Context , * txtypes.TxDecodeAminoRequest ) (* txtypes.TxDecodeAminoResponse , error ) {
185- return nil , status .Error (codes .Unimplemented , "not implemented" )
167+ func (t txServer [T ]) TxDecodeAmino (_ context.Context , req * txtypes.TxDecodeAminoRequest ) (* txtypes.TxDecodeAminoResponse , error ) {
168+ if req .AminoBinary == nil {
169+ return nil , status .Error (codes .InvalidArgument , "invalid empty tx bytes" )
170+ }
171+
172+ var stdTx legacytx.StdTx
173+ err := t .clientCtx .LegacyAmino .Unmarshal (req .AminoBinary , & stdTx )
174+ if err != nil {
175+ return nil , err
176+ }
177+
178+ res , err := t .clientCtx .LegacyAmino .MarshalJSON (stdTx )
179+ if err != nil {
180+ return nil , err
181+ }
182+
183+ return & txtypes.TxDecodeAminoResponse {
184+ AminoJson : string (res ),
185+ }, nil
186186}
187187
188188// TxEncode implements tx.ServiceServer.
189- func (t txServer [T ]) TxEncode (context.Context , * txtypes.TxEncodeRequest ) (* txtypes.TxEncodeResponse , error ) {
190- return nil , status .Error (codes .Unimplemented , "not implemented" )
189+ func (t txServer [T ]) TxEncode (_ context.Context , req * txtypes.TxEncodeRequest ) (* txtypes.TxEncodeResponse , error ) {
190+ if req .Tx == nil {
191+ return nil , status .Error (codes .InvalidArgument , "invalid empty tx" )
192+ }
193+
194+ bodyBytes , err := t .clientCtx .Codec .Marshal (req .Tx .Body )
195+ if err != nil {
196+ return nil , err
197+ }
198+
199+ authInfoBytes , err := t .clientCtx .Codec .Marshal (req .Tx .AuthInfo )
200+ if err != nil {
201+ return nil , err
202+ }
203+
204+ raw := & txtypes.TxRaw {
205+ BodyBytes : bodyBytes ,
206+ AuthInfoBytes : authInfoBytes ,
207+ Signatures : req .Tx .Signatures ,
208+ }
209+
210+ encodedBytes , err := t .clientCtx .Codec .Marshal (raw )
211+ if err != nil {
212+ return nil , err
213+ }
214+
215+ return & txtypes.TxEncodeResponse {
216+ TxBytes : encodedBytes ,
217+ }, nil
191218}
192219
193220// TxEncodeAmino implements tx.ServiceServer.
194- func (t txServer [T ]) TxEncodeAmino (context.Context , * txtypes.TxEncodeAminoRequest ) (* txtypes.TxEncodeAminoResponse , error ) {
195- return nil , status .Error (codes .Unimplemented , "not implemented" )
221+ func (t txServer [T ]) TxEncodeAmino (_ context.Context , req * txtypes.TxEncodeAminoRequest ) (* txtypes.TxEncodeAminoResponse , error ) {
222+ if req .AminoJson == "" {
223+ return nil , status .Error (codes .InvalidArgument , "invalid empty tx json" )
224+ }
225+
226+ var stdTx legacytx.StdTx
227+ err := t .clientCtx .LegacyAmino .UnmarshalJSON ([]byte (req .AminoJson ), & stdTx )
228+ if err != nil {
229+ return nil , err
230+ }
231+
232+ encodedBytes , err := t .clientCtx .LegacyAmino .Marshal (stdTx )
233+ if err != nil {
234+ return nil , err
235+ }
236+
237+ return & txtypes.TxEncodeAminoResponse {
238+ AminoBinary : encodedBytes ,
239+ }, nil
196240}
197241
198242var _ txtypes.ServiceServer = txServer [transaction.Tx ]{}
@@ -236,3 +280,48 @@ func (s nodeServer[T]) Status(ctx context.Context, _ *nodeservice.StatusRequest)
236280 ValidatorHash : nodeInfo .LastBlockAppHash ,
237281 }, nil
238282}
283+
284+ // CometBFTAutoCLIDescriptor is the auto-generated CLI descriptor for the CometBFT service
285+ var CometBFTAutoCLIDescriptor = & autocliv1.ServiceCommandDescriptor {
286+ Service : cmtv1beta1 .Service_ServiceDesc .ServiceName ,
287+ RpcCommandOptions : []* autocliv1.RpcCommandOptions {
288+ {
289+ RpcMethod : "GetNodeInfo" ,
290+ Use : "node-info" ,
291+ Short : "Query the current node info" ,
292+ },
293+ {
294+ RpcMethod : "GetSyncing" ,
295+ Use : "syncing" ,
296+ Short : "Query node syncing status" ,
297+ },
298+ {
299+ RpcMethod : "GetLatestBlock" ,
300+ Use : "block-latest" ,
301+ Short : "Query for the latest committed block" ,
302+ },
303+ {
304+ RpcMethod : "GetBlockByHeight" ,
305+ Use : "block-by-height <height>" ,
306+ Short : "Query for a committed block by height" ,
307+ Long : "Query for a specific committed block using the CometBFT RPC `block_by_height` method" ,
308+ PositionalArgs : []* autocliv1.PositionalArgDescriptor {{ProtoField : "height" }},
309+ },
310+ {
311+ RpcMethod : "GetLatestValidatorSet" ,
312+ Use : "validator-set" ,
313+ Alias : []string {"validator-set-latest" , "comet-validator-set" , "cometbft-validator-set" , "tendermint-validator-set" },
314+ Short : "Query for the latest validator set" ,
315+ },
316+ {
317+ RpcMethod : "GetValidatorSetByHeight" ,
318+ Use : "validator-set-by-height <height>" ,
319+ Short : "Query for a validator set by height" ,
320+ PositionalArgs : []* autocliv1.PositionalArgDescriptor {{ProtoField : "height" }},
321+ },
322+ {
323+ RpcMethod : "ABCIQuery" ,
324+ Skip : true ,
325+ },
326+ },
327+ }
0 commit comments