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

     1  package rpcevent
     2  
     3  import (
     4  	"github.com/nspcc-dev/neo-go/pkg/core/block"
     5  	"github.com/nspcc-dev/neo-go/pkg/core/state"
     6  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
     7  	"github.com/nspcc-dev/neo-go/pkg/neorpc"
     8  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
     9  )
    10  
    11  type (
    12  	// Comparator is an interface required from notification event filter to be able to
    13  	// filter notifications.
    14  	Comparator interface {
    15  		EventID() neorpc.EventID
    16  		Filter() neorpc.SubscriptionFilter
    17  	}
    18  	// Container is an interface required from notification event to be able to
    19  	// pass filter.
    20  	Container interface {
    21  		EventID() neorpc.EventID
    22  		EventPayload() any
    23  	}
    24  )
    25  
    26  // Matches filters our given Container against Comparator filter.
    27  func Matches(f Comparator, r Container) bool {
    28  	expectedEvent := f.EventID()
    29  	filter := f.Filter()
    30  	if r.EventID() != expectedEvent {
    31  		return false
    32  	}
    33  	if filter == nil {
    34  		return true
    35  	}
    36  	switch f.EventID() {
    37  	case neorpc.BlockEventID, neorpc.HeaderOfAddedBlockEventID:
    38  		filt := filter.(neorpc.BlockFilter)
    39  		var b *block.Header
    40  		if f.EventID() == neorpc.HeaderOfAddedBlockEventID {
    41  			b = r.EventPayload().(*block.Header)
    42  		} else {
    43  			b = &r.EventPayload().(*block.Block).Header
    44  		}
    45  		primaryOk := filt.Primary == nil || *filt.Primary == b.PrimaryIndex
    46  		sinceOk := filt.Since == nil || *filt.Since <= b.Index
    47  		tillOk := filt.Till == nil || b.Index <= *filt.Till
    48  		return primaryOk && sinceOk && tillOk
    49  	case neorpc.TransactionEventID:
    50  		filt := filter.(neorpc.TxFilter)
    51  		tx := r.EventPayload().(*transaction.Transaction)
    52  		senderOK := filt.Sender == nil || tx.Sender().Equals(*filt.Sender)
    53  		signerOK := true
    54  		if filt.Signer != nil {
    55  			signerOK = false
    56  			for i := range tx.Signers {
    57  				if tx.Signers[i].Account.Equals(*filt.Signer) {
    58  					signerOK = true
    59  					break
    60  				}
    61  			}
    62  		}
    63  		return senderOK && signerOK
    64  	case neorpc.NotificationEventID:
    65  		filt := filter.(neorpc.NotificationFilter)
    66  		notification := r.EventPayload().(*state.ContainedNotificationEvent)
    67  		hashOk := filt.Contract == nil || notification.ScriptHash.Equals(*filt.Contract)
    68  		nameOk := filt.Name == nil || notification.Name == *filt.Name
    69  		return hashOk && nameOk
    70  	case neorpc.ExecutionEventID:
    71  		filt := filter.(neorpc.ExecutionFilter)
    72  		applog := r.EventPayload().(*state.AppExecResult)
    73  		stateOK := filt.State == nil || applog.VMState.String() == *filt.State
    74  		containerOK := filt.Container == nil || applog.Container.Equals(*filt.Container)
    75  		return stateOK && containerOK
    76  	case neorpc.NotaryRequestEventID:
    77  		filt := filter.(neorpc.NotaryRequestFilter)
    78  		req := r.EventPayload().(*result.NotaryRequestEvent)
    79  		typeOk := filt.Type == nil || req.Type == *filt.Type
    80  		senderOk := filt.Sender == nil || req.NotaryRequest.FallbackTransaction.Signers[1].Account == *filt.Sender
    81  		signerOK := true
    82  		if filt.Signer != nil {
    83  			signerOK = false
    84  			for _, signer := range req.NotaryRequest.MainTransaction.Signers {
    85  				if signer.Account.Equals(*filt.Signer) {
    86  					signerOK = true
    87  					break
    88  				}
    89  			}
    90  		}
    91  		return senderOk && signerOK && typeOk
    92  	}
    93  	return false
    94  }