github.com/Finschia/finschia-sdk@v0.49.1/x/auth/tx2/service.go (about) 1 package tx2 2 3 import ( 4 "context" 5 6 gogogrpc "github.com/gogo/protobuf/grpc" 7 "github.com/grpc-ecosystem/grpc-gateway/runtime" 8 "google.golang.org/grpc/codes" 9 "google.golang.org/grpc/status" 10 11 "github.com/Finschia/finschia-sdk/client" 12 "github.com/Finschia/finschia-sdk/client/grpc/tmservice" 13 codectypes "github.com/Finschia/finschia-sdk/codec/types" 14 sdk "github.com/Finschia/finschia-sdk/types" 15 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 16 pagination "github.com/Finschia/finschia-sdk/types/query" 17 txtypes "github.com/Finschia/finschia-sdk/types/tx" 18 tx2types "github.com/Finschia/finschia-sdk/types/tx2" 19 ) 20 21 type tx2Server struct { 22 clientCtx client.Context 23 interfaceRegistry codectypes.InterfaceRegistry 24 } 25 26 func NewTx2Server(clientCtx client.Context, interfaceRegistry codectypes.InterfaceRegistry) tx2types.ServiceServer { 27 return tx2Server{ 28 clientCtx: clientCtx, 29 interfaceRegistry: interfaceRegistry, 30 } 31 } 32 33 var _ tx2types.ServiceServer = tx2Server{} 34 35 // protoTxProvider is a type which can provide a proto transaction. It is a 36 // workaround to get access to the wrapper TxBuilder's method GetProtoTx(). 37 // ref: https://github.com/cosmos/cosmos-sdk/issues/10347 38 type protoTxProvider interface { 39 GetProtoTx() *txtypes.Tx 40 } 41 42 func (s tx2Server) GetBlockWithTxs(ctx context.Context, req *tx2types.GetBlockWithTxsRequest) (*tx2types.GetBlockWithTxsResponse, error) { 43 if req == nil { 44 return nil, status.Error(codes.InvalidArgument, "request cannot be nil") 45 } 46 47 sdkCtx := sdk.UnwrapSDKContext(ctx) 48 currentHeight := sdkCtx.BlockHeight() 49 50 if req.Height < 1 || req.Height > currentHeight { 51 return nil, sdkerrors.ErrInvalidHeight.Wrapf("requested height %d but height must not be less than 1 "+ 52 "or greater than the current height %d", req.Height, currentHeight) 53 } 54 55 blockID, block, err := tmservice.GetProtoBlock(ctx, s.clientCtx, &req.Height) 56 if err != nil { 57 return nil, err 58 } 59 60 var offset, limit uint64 61 if req.Pagination != nil { 62 offset = req.Pagination.Offset 63 limit = req.Pagination.Limit 64 } else { 65 offset = 0 66 limit = pagination.DefaultLimit 67 } 68 69 blockTxs := block.Data.Txs 70 blockTxsLn := uint64(len(blockTxs)) 71 txs := make([]*txtypes.Tx, 0, limit) 72 if offset >= blockTxsLn && blockTxsLn != 0 { 73 return nil, sdkerrors.ErrInvalidRequest.Wrapf("out of range: cannot paginate %d txs with offset %d and limit %d", blockTxsLn, offset, limit) 74 } 75 decodeTxAt := func(i uint64) error { 76 tx := blockTxs[i] 77 txb, err := s.clientCtx.TxConfig.TxDecoder()(tx) 78 if err != nil { 79 return err 80 } 81 p, ok := txb.(protoTxProvider) 82 if !ok { 83 return sdkerrors.ErrTxDecode.Wrapf("could not cast %T to %T", txb, txtypes.Tx{}) 84 } 85 txs = append(txs, p.GetProtoTx()) 86 return nil 87 } 88 if req.Pagination != nil && req.Pagination.Reverse { 89 for i, count := offset, uint64(0); i > 0 && count != limit; i, count = i-1, count+1 { 90 if err = decodeTxAt(i); err != nil { 91 return nil, err 92 } 93 } 94 } else { 95 for i, count := offset, uint64(0); i < blockTxsLn && count != limit; i, count = i+1, count+1 { 96 if err = decodeTxAt(i); err != nil { 97 return nil, err 98 } 99 } 100 } 101 102 return &tx2types.GetBlockWithTxsResponse{ 103 Txs: txs, 104 BlockId: &blockID, 105 Block: block, 106 Pagination: &pagination.PageResponse{ 107 Total: blockTxsLn, 108 }, 109 }, nil 110 } 111 112 // RegisterTxService registers the tx service on the gRPC router. 113 func RegisterTxService( 114 qrt gogogrpc.Server, 115 clientCtx client.Context, 116 interfaceRegistry codectypes.InterfaceRegistry, 117 ) { 118 tx2types.RegisterServiceServer( 119 qrt, 120 NewTx2Server(clientCtx, interfaceRegistry), 121 ) 122 } 123 124 // RegisterGRPCGatewayRoutes mounts the tx service's GRPC-gateway routes on the 125 // given Mux. 126 func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) { 127 if err := tx2types.RegisterServiceHandlerClient(context.Background(), mux, tx2types.NewServiceClient(clientConn)); err != nil { 128 panic(err) 129 } 130 }