code: func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client, error) {
  
  	channelContext, err := channelProvider()
  	if err != nil {
  		return nil, err
  	}
  
  	if channelContext.ChannelService() == nil {
  		return nil, errors.New("channel service not initialized")
  	}
  
  	membership, err := channelContext.ChannelService().Membership()
  	if err != nil {
  		return nil, errors.WithMessage(err, "membership creation failed")
  	}
  
  	ledger, err := channel.NewLedger(channelContext.ChannelID())
  	if err != nil {
  		return nil, err
  	}
  
  	ledgerFilter := filter.NewEndpointFilter(channelContext, filter.LedgerQuery)
  
  	discoveryService, err := channelContext.ChannelService().Discovery()
  	if err != nil {
  		return nil, err
  	}
  
  	// Apply filter to discovery service
  	discovery := discovery.NewDiscoveryFilterService(discoveryService, ledgerFilter)
  
  	ledgerClient := Client{
  		ctx:       channelContext,
  		ledger:    ledger,
  		verifier:  &verifier.Signature{Membership: membership},
  		discovery: discovery,
  	}
  
  	for _, opt := range opts {
  		err := opt(&ledgerClient)
  		if err != nil {
  			return nil, err
  		}
  	}
  
  	// check if target filter was set - if not set the default
  	if ledgerClient.filter == nil {
  		// Default target filter is based on user msp
  		if channelContext.Identifier().MSPID == "" {
  			return nil, errors.New("mspID not available in user context")
  		}
  		filter := &mspFilter{mspID: channelContext.Identifier().MSPID}
  		ledgerClient.filter = filter
  	}
  
  	return &ledgerClient, nil
  }
docs: // New returns a ledger client instance. A ledger client instance provides a handler to query various info on specified channel.
  // An application that requires interaction with multiple channels should create a separate
  // instance of the ledger client for each channel. Ledger client supports specific queries only.