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  }