github.com/s7techlab/cckit@v0.10.5/gateway/chaincode_instance_service.go (about)

     1  package gateway
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/hyperledger/fabric-protos-go/peer"
     8  
     9  	"github.com/s7techlab/cckit/router"
    10  	"github.com/s7techlab/cckit/sdk"
    11  )
    12  
    13  type (
    14  	ChaincodeInstanceService struct {
    15  		SDK     sdk.SDK
    16  		Locator *ChaincodeLocator
    17  		Opts    *Opts
    18  	}
    19  
    20  	// ChaincodeInstance base implementation ChaincodeInstanceService  - via SDK
    21  	// but also possible another implementation (via REST, another SDK etc)
    22  	ChaincodeInstance interface {
    23  		ChaincodeInstanceServiceServer
    24  
    25  		EventsChan(ctx context.Context, rr ...*ChaincodeInstanceEventsStreamRequest) (
    26  			_ chan *ChaincodeEvent, closer func() error, _ error)
    27  	}
    28  )
    29  
    30  var _ ChaincodeInstance = &ChaincodeInstanceService{}
    31  
    32  func NewChaincodeInstanceService(sdk sdk.SDK, locator *ChaincodeLocator, opts ...Opt) *ChaincodeInstanceService {
    33  	ccInstanceService := &ChaincodeInstanceService{
    34  		SDK:     sdk,
    35  		Locator: locator,
    36  		Opts:    &Opts{},
    37  	}
    38  
    39  	for _, o := range opts {
    40  		o(ccInstanceService.Opts)
    41  	}
    42  
    43  	return ccInstanceService
    44  }
    45  
    46  func (cis *ChaincodeInstanceService) EventService() *ChaincodeInstanceEventService {
    47  	return &ChaincodeInstanceEventService{
    48  		EventDelivery: cis.SDK,
    49  		Locator: &ChaincodeLocator{
    50  			Channel:   cis.Locator.Channel,
    51  			Chaincode: cis.Locator.Chaincode,
    52  		},
    53  		Opts: cis.Opts,
    54  	}
    55  }
    56  
    57  func (cis *ChaincodeInstanceService) ServiceDef() ServiceDef {
    58  	return ServiceDef{
    59  		Desc:                        &_ChaincodeInstanceService_serviceDesc,
    60  		Service:                     cis,
    61  		HandlerFromEndpointRegister: RegisterChaincodeInstanceServiceHandlerFromEndpoint,
    62  	}
    63  }
    64  
    65  func (cis *ChaincodeInstanceService) Exec(ctx context.Context, req *ChaincodeInstanceExecRequest) (*peer.Response, error) {
    66  	switch req.Type {
    67  	case InvocationType_INVOCATION_TYPE_QUERY:
    68  		return cis.Query(ctx, &ChaincodeInstanceQueryRequest{Input: req.Input})
    69  	case InvocationType_INVOCATION_TYPE_INVOKE:
    70  		return cis.Invoke(ctx, &ChaincodeInstanceInvokeRequest{Input: req.Input})
    71  	default:
    72  		return nil, ErrUnknownInvocationType
    73  	}
    74  }
    75  
    76  func (cis *ChaincodeInstanceService) Query(ctx context.Context, req *ChaincodeInstanceQueryRequest) (*peer.Response, error) {
    77  	if err := router.ValidateRequest(req); err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	for _, c := range cis.Opts.Context {
    82  		ctx = c(ctx)
    83  	}
    84  
    85  	signer, _ := SignerFromContext(ctx)
    86  
    87  	for _, i := range cis.Opts.Input {
    88  		if err := i(req.Input); err != nil {
    89  			return nil, err
    90  		}
    91  	}
    92  
    93  	response, err := cis.SDK.Query(
    94  		ctx,
    95  		cis.Locator.Channel,
    96  		cis.Locator.Chaincode,
    97  		req.Input.Args,
    98  		signer,
    99  		req.Input.Transient,
   100  	)
   101  	if err != nil {
   102  		return nil, fmt.Errorf("query chaincode: %w", err)
   103  	}
   104  	for _, o := range cis.Opts.Output {
   105  		if err = o(InvocationType_INVOCATION_TYPE_QUERY, response); err != nil {
   106  			return nil, fmt.Errorf(`output opt: %w`, err)
   107  		}
   108  	}
   109  
   110  	return response, nil
   111  
   112  }
   113  
   114  func (cis *ChaincodeInstanceService) Invoke(ctx context.Context, req *ChaincodeInstanceInvokeRequest) (*peer.Response, error) {
   115  	if err := router.ValidateRequest(req); err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	for _, c := range cis.Opts.Context {
   120  		ctx = c(ctx)
   121  	}
   122  
   123  	// underlying hlf-sdk(or your implementation must handle it) should handle 'nil' identity cases
   124  	// and set default if identity wasn't provided here
   125  	// if smth goes wrong we'll see it on the step below
   126  	signer, _ := SignerFromContext(ctx)
   127  
   128  	for _, i := range cis.Opts.Input {
   129  		if err := i(req.Input); err != nil {
   130  			return nil, err
   131  		}
   132  	}
   133  
   134  	response, _, err := cis.SDK.Invoke(
   135  		ctx,
   136  		cis.Locator.Channel,
   137  		cis.Locator.Chaincode,
   138  		req.Input.Args,
   139  		signer,
   140  		req.Input.Transient,
   141  		TxWaiterFromContext(ctx),
   142  	)
   143  	if err != nil {
   144  		return nil, fmt.Errorf("invoke chaincode: %w", err)
   145  	}
   146  
   147  	for _, o := range cis.Opts.Output {
   148  		if err = o(InvocationType_INVOCATION_TYPE_INVOKE, response); err != nil {
   149  			return nil, fmt.Errorf(`output opt: %w`, err)
   150  		}
   151  	}
   152  
   153  	return response, nil
   154  }
   155  
   156  func (cis *ChaincodeInstanceService) EventsStream(
   157  	req *ChaincodeInstanceEventsStreamRequest, stream ChaincodeInstanceService_EventsStreamServer) error {
   158  	return cis.EventService().EventsStream(req, stream)
   159  }
   160  
   161  func (cis *ChaincodeInstanceService) Events(
   162  	ctx context.Context, req *ChaincodeInstanceEventsRequest) (*ChaincodeEvents, error) {
   163  	return cis.EventService().Events(ctx, req)
   164  }
   165  
   166  func (cis *ChaincodeInstanceService) EventsChan(
   167  	ctx context.Context, rr ...*ChaincodeInstanceEventsStreamRequest) (_ chan *ChaincodeEvent, closer func() error, _ error) {
   168  	return cis.EventService().EventsChan(ctx, rr...)
   169  }