github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/neorpc/filters.go (about)

     1  package neorpc
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
     8  	"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
     9  	"github.com/nspcc-dev/neo-go/pkg/util"
    10  	"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
    11  )
    12  
    13  type (
    14  	// BlockFilter is a wrapper structure for the block event filter. It allows
    15  	// to filter blocks by primary index and/or by block index (allowing blocks
    16  	// since/till the specified index inclusively). nil value treated as missing
    17  	// filter.
    18  	BlockFilter struct {
    19  		Primary *byte   `json:"primary,omitempty"`
    20  		Since   *uint32 `json:"since,omitempty"`
    21  		Till    *uint32 `json:"till,omitempty"`
    22  	}
    23  	// TxFilter is a wrapper structure for the transaction event filter. It
    24  	// allows to filter transactions by senders and/or signers. nil value treated
    25  	// as missing filter.
    26  	TxFilter struct {
    27  		Sender *util.Uint160 `json:"sender,omitempty"`
    28  		Signer *util.Uint160 `json:"signer,omitempty"`
    29  	}
    30  	// NotificationFilter is a wrapper structure representing a filter used for
    31  	// notifications generated during transaction execution. Notifications can
    32  	// be filtered by contract hash and/or by name. nil value treated as missing
    33  	// filter.
    34  	NotificationFilter struct {
    35  		Contract *util.Uint160 `json:"contract,omitempty"`
    36  		Name     *string       `json:"name,omitempty"`
    37  	}
    38  	// ExecutionFilter is a wrapper structure used for transaction and persisting
    39  	// scripts execution events. It allows to choose failing or successful
    40  	// transactions and persisting scripts based on their VM state and/or to
    41  	// choose execution event with the specified container. nil value treated as
    42  	// missing filter.
    43  	ExecutionFilter struct {
    44  		State     *string       `json:"state,omitempty"`
    45  		Container *util.Uint256 `json:"container,omitempty"`
    46  	}
    47  	// NotaryRequestFilter is a wrapper structure used for notary request events.
    48  	// It allows to choose notary request events with the specified request sender,
    49  	// main transaction signer and/or type. nil value treated as missing filter.
    50  	NotaryRequestFilter struct {
    51  		Sender *util.Uint160      `json:"sender,omitempty"`
    52  		Signer *util.Uint160      `json:"signer,omitempty"`
    53  		Type   *mempoolevent.Type `json:"type,omitempty"`
    54  	}
    55  )
    56  
    57  // SubscriptionFilter is an interface for all subscription filters.
    58  type SubscriptionFilter interface {
    59  	// IsValid checks whether the filter is valid and returns
    60  	// a specific [ErrInvalidSubscriptionFilter] error if not.
    61  	IsValid() error
    62  }
    63  
    64  // ErrInvalidSubscriptionFilter is returned when the subscription filter is invalid.
    65  var ErrInvalidSubscriptionFilter = errors.New("invalid subscription filter")
    66  
    67  // Copy creates a deep copy of the BlockFilter. It handles nil BlockFilter correctly.
    68  func (f *BlockFilter) Copy() *BlockFilter {
    69  	if f == nil {
    70  		return nil
    71  	}
    72  	var res = new(BlockFilter)
    73  	if f.Primary != nil {
    74  		res.Primary = new(byte)
    75  		*res.Primary = *f.Primary
    76  	}
    77  	if f.Since != nil {
    78  		res.Since = new(uint32)
    79  		*res.Since = *f.Since
    80  	}
    81  	if f.Till != nil {
    82  		res.Till = new(uint32)
    83  		*res.Till = *f.Till
    84  	}
    85  	return res
    86  }
    87  
    88  // IsValid implements SubscriptionFilter interface.
    89  func (f BlockFilter) IsValid() error {
    90  	return nil
    91  }
    92  
    93  // Copy creates a deep copy of the TxFilter. It handles nil TxFilter correctly.
    94  func (f *TxFilter) Copy() *TxFilter {
    95  	if f == nil {
    96  		return nil
    97  	}
    98  	var res = new(TxFilter)
    99  	if f.Sender != nil {
   100  		res.Sender = new(util.Uint160)
   101  		*res.Sender = *f.Sender
   102  	}
   103  	if f.Signer != nil {
   104  		res.Signer = new(util.Uint160)
   105  		*res.Signer = *f.Signer
   106  	}
   107  	return res
   108  }
   109  
   110  // IsValid implements SubscriptionFilter interface.
   111  func (f TxFilter) IsValid() error {
   112  	return nil
   113  }
   114  
   115  // Copy creates a deep copy of the NotificationFilter. It handles nil NotificationFilter correctly.
   116  func (f *NotificationFilter) Copy() *NotificationFilter {
   117  	if f == nil {
   118  		return nil
   119  	}
   120  	var res = new(NotificationFilter)
   121  	if f.Contract != nil {
   122  		res.Contract = new(util.Uint160)
   123  		*res.Contract = *f.Contract
   124  	}
   125  	if f.Name != nil {
   126  		res.Name = new(string)
   127  		*res.Name = *f.Name
   128  	}
   129  	return res
   130  }
   131  
   132  // IsValid implements SubscriptionFilter interface.
   133  func (f NotificationFilter) IsValid() error {
   134  	if f.Name != nil && len(*f.Name) > runtime.MaxEventNameLen {
   135  		return fmt.Errorf("%w: NotificationFilter name parameter must be less than %d", ErrInvalidSubscriptionFilter, runtime.MaxEventNameLen)
   136  	}
   137  	return nil
   138  }
   139  
   140  // Copy creates a deep copy of the ExecutionFilter. It handles nil ExecutionFilter correctly.
   141  func (f *ExecutionFilter) Copy() *ExecutionFilter {
   142  	if f == nil {
   143  		return nil
   144  	}
   145  	var res = new(ExecutionFilter)
   146  	if f.State != nil {
   147  		res.State = new(string)
   148  		*res.State = *f.State
   149  	}
   150  	if f.Container != nil {
   151  		res.Container = new(util.Uint256)
   152  		*res.Container = *f.Container
   153  	}
   154  	return res
   155  }
   156  
   157  // IsValid implements SubscriptionFilter interface.
   158  func (f ExecutionFilter) IsValid() error {
   159  	if f.State != nil {
   160  		if *f.State != vmstate.Halt.String() && *f.State != vmstate.Fault.String() {
   161  			return fmt.Errorf("%w: ExecutionFilter state parameter must be either %s or %s", ErrInvalidSubscriptionFilter, vmstate.Halt, vmstate.Fault)
   162  		}
   163  	}
   164  
   165  	return nil
   166  }
   167  
   168  // Copy creates a deep copy of the NotaryRequestFilter. It handles nil NotaryRequestFilter correctly.
   169  func (f *NotaryRequestFilter) Copy() *NotaryRequestFilter {
   170  	if f == nil {
   171  		return nil
   172  	}
   173  	var res = new(NotaryRequestFilter)
   174  	if f.Sender != nil {
   175  		res.Sender = new(util.Uint160)
   176  		*res.Sender = *f.Sender
   177  	}
   178  	if f.Signer != nil {
   179  		res.Signer = new(util.Uint160)
   180  		*res.Signer = *f.Signer
   181  	}
   182  	if f.Type != nil {
   183  		res.Type = new(mempoolevent.Type)
   184  		*res.Type = *f.Type
   185  	}
   186  	return res
   187  }
   188  
   189  // IsValid implements SubscriptionFilter interface.
   190  func (f NotaryRequestFilter) IsValid() error {
   191  	return nil
   192  }